@aura3d/cli 1.3.3 → 1.4.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/asset-constants.d.ts +5 -0
- package/dist/asset-constants.d.ts.map +1 -0
- package/dist/asset-constants.js +5 -0
- package/dist/asset-constants.js.map +1 -0
- package/dist/asset-core-types.d.ts +206 -0
- package/dist/asset-core-types.d.ts.map +1 -0
- package/dist/asset-core-types.js +2 -0
- package/dist/asset-core-types.js.map +1 -0
- package/dist/asset-inspection-types.d.ts +131 -0
- package/dist/asset-inspection-types.d.ts.map +1 -0
- package/dist/asset-inspection-types.js +2 -0
- package/dist/asset-inspection-types.js.map +1 -0
- package/dist/asset-manifest.d.ts +8 -0
- package/dist/asset-manifest.d.ts.map +1 -0
- package/dist/asset-manifest.js +116 -0
- package/dist/asset-manifest.js.map +1 -0
- package/dist/asset-readiness-types.d.ts +164 -0
- package/dist/asset-readiness-types.d.ts.map +1 -0
- package/dist/asset-readiness-types.js +2 -0
- package/dist/asset-readiness-types.js.map +1 -0
- package/dist/asset-source-ast.d.ts +8 -0
- package/dist/asset-source-ast.d.ts.map +1 -0
- package/dist/asset-source-ast.js +241 -0
- package/dist/asset-source-ast.js.map +1 -0
- package/dist/asset-source-roles.d.ts +4 -0
- package/dist/asset-source-roles.d.ts.map +1 -0
- package/dist/asset-source-roles.js +79 -0
- package/dist/asset-source-roles.js.map +1 -0
- package/dist/asset-source-validation.d.ts +4 -0
- package/dist/asset-source-validation.d.ts.map +1 -0
- package/dist/asset-source-validation.js +200 -0
- package/dist/asset-source-validation.js.map +1 -0
- package/dist/character-assembly-types.d.ts +39 -0
- package/dist/character-assembly-types.d.ts.map +1 -0
- package/dist/character-assembly-types.js +2 -0
- package/dist/character-assembly-types.js.map +1 -0
- package/dist/cli-help.d.ts +4 -0
- package/dist/cli-help.d.ts.map +1 -0
- package/dist/cli-help.js +48 -0
- package/dist/cli-help.js.map +1 -0
- package/dist/cli-options.d.ts +66 -0
- package/dist/cli-options.d.ts.map +1 -0
- package/dist/cli-options.js +234 -0
- package/dist/cli-options.js.map +1 -0
- package/dist/cli.js +20 -177
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +12 -402
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +948 -90
- package/dist/index.js.map +1 -1
- package/dist/pull-bridge/adapters.d.ts +4 -0
- package/dist/pull-bridge/adapters.d.ts.map +1 -0
- package/dist/pull-bridge/adapters.js +38 -0
- package/dist/pull-bridge/adapters.js.map +1 -0
- package/dist/pull-bridge/download.d.ts +6 -0
- package/dist/pull-bridge/download.d.ts.map +1 -0
- package/dist/pull-bridge/download.js +208 -0
- package/dist/pull-bridge/download.js.map +1 -0
- package/dist/pull-bridge/profiles.d.ts +14 -0
- package/dist/pull-bridge/profiles.d.ts.map +1 -0
- package/dist/pull-bridge/profiles.js +63 -0
- package/dist/pull-bridge/profiles.js.map +1 -0
- package/dist/pull-bridge/provenance.d.ts +9 -0
- package/dist/pull-bridge/provenance.d.ts.map +1 -0
- package/dist/pull-bridge/provenance.js +99 -0
- package/dist/pull-bridge/provenance.js.map +1 -0
- package/dist/pull-bridge/pullable.d.ts +14 -0
- package/dist/pull-bridge/pullable.d.ts.map +1 -0
- package/dist/pull-bridge/pullable.js +58 -0
- package/dist/pull-bridge/pullable.js.map +1 -0
- package/dist/pull-bridge/scoring.d.ts +21 -0
- package/dist/pull-bridge/scoring.d.ts.map +1 -0
- package/dist/pull-bridge/scoring.js +177 -0
- package/dist/pull-bridge/scoring.js.map +1 -0
- package/dist/pull-bridge/search.d.ts +39 -0
- package/dist/pull-bridge/search.d.ts.map +1 -0
- package/dist/pull-bridge/search.js +114 -0
- package/dist/pull-bridge/search.js.map +1 -0
- package/dist/pull-bridge/types.d.ts +9 -0
- package/dist/pull-bridge/types.d.ts.map +1 -0
- package/dist/pull-bridge/types.js +2 -0
- package/dist/pull-bridge/types.js.map +1 -0
- package/dist/pull-bridge/vector3.d.ts +2 -0
- package/dist/pull-bridge/vector3.d.ts.map +1 -0
- package/dist/pull-bridge/vector3.js +4 -0
- package/dist/pull-bridge/vector3.js.map +1 -0
- package/dist/pull-bridge.d.ts +18 -100
- package/dist/pull-bridge.d.ts.map +1 -1
- package/dist/pull-bridge.js +59 -526
- package/dist/pull-bridge.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { isPositiveVector3 } from "./vector3.js";
|
|
2
|
+
export function scoreResolveCandidate(candidate, options = {}) {
|
|
3
|
+
const asset = candidate.asset;
|
|
4
|
+
const reasons = [];
|
|
5
|
+
const penalties = [];
|
|
6
|
+
const query = options.query ?? "";
|
|
7
|
+
const semantic = scoreSignal(candidate.score, 12) +
|
|
8
|
+
scoreSignal(asset.semanticScore, 8) +
|
|
9
|
+
scoreSignal(asset.workerScore, 4) +
|
|
10
|
+
scoreSignal(asset.qualityScore, 4);
|
|
11
|
+
if (semantic > 0)
|
|
12
|
+
reasons.push(`semantic/source score ${roundScore(semantic)}`);
|
|
13
|
+
let sourceQuality = 0;
|
|
14
|
+
if (asset.sourcePage) {
|
|
15
|
+
sourceQuality += 6;
|
|
16
|
+
reasons.push("source page preserved");
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
penalties.push("missing source page");
|
|
20
|
+
}
|
|
21
|
+
if (asset.downloadUrl ?? asset.url) {
|
|
22
|
+
sourceQuality += 5;
|
|
23
|
+
reasons.push("download URL preserved");
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
penalties.push("missing download URL");
|
|
27
|
+
}
|
|
28
|
+
if (asset.author ?? asset.attribution) {
|
|
29
|
+
sourceQuality += 4;
|
|
30
|
+
reasons.push("author/attribution preserved");
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
penalties.push("missing author/attribution");
|
|
34
|
+
}
|
|
35
|
+
if (asset.sourceFamily ?? asset.source)
|
|
36
|
+
sourceQuality += 3;
|
|
37
|
+
if (asset.retrievedAt)
|
|
38
|
+
sourceQuality += 2;
|
|
39
|
+
if (asset.rawCatalogMetadata)
|
|
40
|
+
sourceQuality += 2;
|
|
41
|
+
let license = 0;
|
|
42
|
+
if (asset.license.verified && asset.license.redistributable) {
|
|
43
|
+
license += 10;
|
|
44
|
+
reasons.push(`verified ${asset.license.spdx} license`);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
penalties.push("license is not verified redistributable");
|
|
48
|
+
}
|
|
49
|
+
if (asset.licenseName ?? asset.license.raw)
|
|
50
|
+
license += 3;
|
|
51
|
+
if (asset.licenseUrl ?? asset.license.sourcePage)
|
|
52
|
+
license += 4;
|
|
53
|
+
else
|
|
54
|
+
penalties.push("missing license URL/source evidence");
|
|
55
|
+
let inspection = 0;
|
|
56
|
+
const boundsSize = asset.bounds?.size ?? asset.dimensions;
|
|
57
|
+
if (isPositiveVector3(boundsSize)) {
|
|
58
|
+
inspection += 6;
|
|
59
|
+
reasons.push("bounds/dimensions metadata preserved");
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
penalties.push("missing bounds/dimensions metadata");
|
|
63
|
+
}
|
|
64
|
+
const triangles = asset.triangleCount ?? asset.triangles;
|
|
65
|
+
if (typeof triangles === "number" && Number.isFinite(triangles) && triangles > 0)
|
|
66
|
+
inspection += 3;
|
|
67
|
+
if (typeof asset.meshCount === "number" && asset.meshCount > 0)
|
|
68
|
+
inspection += 3;
|
|
69
|
+
if (typeof asset.materialCount === "number" && asset.materialCount > 0)
|
|
70
|
+
inspection += 4;
|
|
71
|
+
else if (expectsVisualMaterials(asset, query))
|
|
72
|
+
penalties.push("missing material metadata for visual model role");
|
|
73
|
+
if (typeof asset.textureCount === "number" && asset.textureCount > 0)
|
|
74
|
+
inspection += 4;
|
|
75
|
+
else if (expectsTextureEvidence(asset, query))
|
|
76
|
+
penalties.push("missing texture metadata for visual model role");
|
|
77
|
+
const clipCount = asset.animationClipCount ?? asset.animationClips?.length;
|
|
78
|
+
if (typeof clipCount === "number" && clipCount > 0)
|
|
79
|
+
inspection += 2;
|
|
80
|
+
if (typeof asset.skinCount === "number" && asset.skinCount > 0)
|
|
81
|
+
inspection += 2;
|
|
82
|
+
if (typeof asset.morphTargetCount === "number" && asset.morphTargetCount > 0)
|
|
83
|
+
inspection += 1;
|
|
84
|
+
let roleFit = 0;
|
|
85
|
+
if (asset.intendedRole && asset.intendedRole !== "unknown") {
|
|
86
|
+
roleFit += 4;
|
|
87
|
+
reasons.push(`intended role ${asset.intendedRole}`);
|
|
88
|
+
}
|
|
89
|
+
const queryRole = inferQueryRole(query, options.profile);
|
|
90
|
+
if (queryRole && asset.intendedRole === queryRole) {
|
|
91
|
+
roleFit += 8;
|
|
92
|
+
reasons.push(`role matches query (${queryRole})`);
|
|
93
|
+
}
|
|
94
|
+
else if (queryRole && asset.intendedRole && asset.intendedRole !== "unknown") {
|
|
95
|
+
penalties.push(`role mismatch: wanted ${queryRole}, got ${asset.intendedRole}`);
|
|
96
|
+
}
|
|
97
|
+
if (asset.roleSuitability && asset.roleSuitability.trim().length >= 16)
|
|
98
|
+
roleFit += 3;
|
|
99
|
+
else if (asset.intendedRole && asset.intendedRole !== "abstract")
|
|
100
|
+
penalties.push("missing role suitability explanation");
|
|
101
|
+
if (asset.qualityWarnings && asset.qualityWarnings.length > 0) {
|
|
102
|
+
for (const warning of asset.qualityWarnings)
|
|
103
|
+
penalties.push(`catalog warning: ${warning}`);
|
|
104
|
+
}
|
|
105
|
+
if (asset.duplicateHash && !asset.duplicateOkReason)
|
|
106
|
+
penalties.push(`duplicate hash ${asset.duplicateHash} lacks allowlist reason`);
|
|
107
|
+
const penaltyCost = penalties.reduce((total, penalty) => {
|
|
108
|
+
if (penalty.includes("duplicate hash"))
|
|
109
|
+
return total + 40;
|
|
110
|
+
if (penalty.includes("license"))
|
|
111
|
+
return total + 20;
|
|
112
|
+
if (penalty.includes("missing source page"))
|
|
113
|
+
return total + 8;
|
|
114
|
+
if (penalty.includes("missing material") || penalty.includes("missing texture"))
|
|
115
|
+
return total + 6;
|
|
116
|
+
if (penalty.includes("role mismatch"))
|
|
117
|
+
return total + 6;
|
|
118
|
+
return total + 3;
|
|
119
|
+
}, 0);
|
|
120
|
+
const total = Math.max(0, semantic + sourceQuality + license + inspection + roleFit - penaltyCost);
|
|
121
|
+
return {
|
|
122
|
+
total: roundScore(total),
|
|
123
|
+
semantic: roundScore(semantic),
|
|
124
|
+
sourceQuality: roundScore(sourceQuality),
|
|
125
|
+
license: roundScore(license),
|
|
126
|
+
inspection: roundScore(inspection),
|
|
127
|
+
roleFit: roundScore(roleFit),
|
|
128
|
+
penalties,
|
|
129
|
+
reasons,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
export function rankResolveCandidates(candidates, options = {}) {
|
|
133
|
+
return [...candidates].sort((a, b) => {
|
|
134
|
+
const aScore = scoreResolveCandidate(a, options);
|
|
135
|
+
const bScore = scoreResolveCandidate(b, options);
|
|
136
|
+
return bScore.total - aScore.total || b.score - a.score || a.asset.id.localeCompare(b.asset.id);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
function scoreSignal(value, scale) {
|
|
140
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0)
|
|
141
|
+
return 0;
|
|
142
|
+
if (value <= 1)
|
|
143
|
+
return value * scale;
|
|
144
|
+
if (value <= 100)
|
|
145
|
+
return (value / 100) * scale;
|
|
146
|
+
return scale;
|
|
147
|
+
}
|
|
148
|
+
function roundScore(value) {
|
|
149
|
+
return Math.round(value * 100) / 100;
|
|
150
|
+
}
|
|
151
|
+
function expectsVisualMaterials(asset, query) {
|
|
152
|
+
const role = asset.intendedRole ?? inferQueryRole(query);
|
|
153
|
+
return role !== "abstract" && role !== "debug";
|
|
154
|
+
}
|
|
155
|
+
function expectsTextureEvidence(asset, query) {
|
|
156
|
+
const role = asset.intendedRole ?? inferQueryRole(query);
|
|
157
|
+
return role === "character" || role === "vehicle" || role === "track" || role === "world" || role === "environment" || role === "product" || role === "weapon";
|
|
158
|
+
}
|
|
159
|
+
function inferQueryRole(query, profile) {
|
|
160
|
+
if (profile === "fighting-character" || profile === "animation-character")
|
|
161
|
+
return "character";
|
|
162
|
+
const text = query.toLowerCase();
|
|
163
|
+
if (/\b(character|avatar|runner|humanoid|person|hero|fighter|enemy|npc)\b/.test(text))
|
|
164
|
+
return "character";
|
|
165
|
+
if (/\b(car|vehicle|truck|ship|plane|drone|kart|race)\b/.test(text))
|
|
166
|
+
return "vehicle";
|
|
167
|
+
if (/\b(track|circuit|road|raceway)\b/.test(text))
|
|
168
|
+
return "track";
|
|
169
|
+
if (/\b(world|level|map|environment|scene|arena)\b/.test(text))
|
|
170
|
+
return "world";
|
|
171
|
+
if (/\b(product|phone|shoe|sneaker|watch|commerce)\b/.test(text))
|
|
172
|
+
return "product";
|
|
173
|
+
if (/\b(weapon|gun|sword|blade)\b/.test(text))
|
|
174
|
+
return "weapon";
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=scoring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoring.js","sourceRoot":"","sources":["../../../../../packages/aura3d-cli/src/pull-bridge/scoring.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { AuraCanonicalAsset, FederatedResolver as FederatedResolverType, ResolveCandidate, SourceAdapter } from "@aura3d/asset-index";
|
|
2
|
+
import type { CliAssetSearchProfile, CliResolveConstraints } from "./types.js";
|
|
3
|
+
export interface SearchOptions {
|
|
4
|
+
readonly query: string;
|
|
5
|
+
readonly constraints?: CliResolveConstraints;
|
|
6
|
+
readonly limit?: number;
|
|
7
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
8
|
+
readonly makeResolver?: (adapters: readonly SourceAdapter[]) => FederatedResolverType;
|
|
9
|
+
}
|
|
10
|
+
export interface SearchCandidateLine {
|
|
11
|
+
readonly id: string;
|
|
12
|
+
readonly source: string;
|
|
13
|
+
readonly title: string;
|
|
14
|
+
readonly license: string;
|
|
15
|
+
readonly autoPullable: boolean;
|
|
16
|
+
readonly access: AuraCanonicalAsset["access"];
|
|
17
|
+
readonly sourcePage?: string;
|
|
18
|
+
readonly profile?: {
|
|
19
|
+
readonly name: Exclude<CliAssetSearchProfile, "general">;
|
|
20
|
+
readonly suitable: boolean;
|
|
21
|
+
readonly rejectionReasons: readonly string[];
|
|
22
|
+
readonly warnings: readonly string[];
|
|
23
|
+
readonly validationHooks: readonly string[];
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export interface SearchReport {
|
|
27
|
+
readonly ok: boolean;
|
|
28
|
+
readonly query: string;
|
|
29
|
+
readonly profile: CliAssetSearchProfile;
|
|
30
|
+
readonly candidates: readonly SearchCandidateLine[];
|
|
31
|
+
readonly rejectedCandidates: readonly SearchCandidateLine[];
|
|
32
|
+
readonly deepLinks: readonly SearchCandidateLine[];
|
|
33
|
+
readonly warnings: readonly string[];
|
|
34
|
+
readonly messages: readonly string[];
|
|
35
|
+
}
|
|
36
|
+
export declare function toLine(candidate: ResolveCandidate, profile?: CliAssetSearchProfile): SearchCandidateLine;
|
|
37
|
+
export declare function makeDefaultResolver(adapters: readonly SourceAdapter[], limit: number): FederatedResolverType;
|
|
38
|
+
export declare function runSearch(options: SearchOptions): Promise<SearchReport>;
|
|
39
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../../../packages/aura3d-cli/src/pull-bridge/search.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,IAAI,qBAAqB,EAC1C,gBAAgB,EAEhB,aAAa,EACd,MAAM,qBAAqB,CAAC;AAW7B,OAAO,KAAK,EACV,qBAAqB,EACrB,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAIpB,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,qBAAqB,CAAC;IAC7C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,KAAK,qBAAqB,CAAC;CACvF;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE;QACjB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,qBAAqB,EAAE,SAAS,CAAC,CAAC;QACzD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;QAC3B,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;QAC7C,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;QACrC,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;KAC7C,CAAC;CACH;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,qBAAqB,CAAC;IACxC,QAAQ,CAAC,UAAU,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACpD,QAAQ,CAAC,kBAAkB,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAC5D,QAAQ,CAAC,SAAS,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACnD,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED,wBAAgB,MAAM,CAAC,SAAS,EAAE,gBAAgB,EAAE,OAAO,GAAE,qBAAiC,GAAG,mBAAmB,CA+BnH;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,SAAS,aAAa,EAAE,EAClC,KAAK,EAAE,MAAM,GACZ,qBAAqB,CAEvB;AAED,wBAAsB,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CA6F7E"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import * as assetIndex from "@aura3d/asset-index";
|
|
2
|
+
import { buildDeepLinkAdapter, buildSearchAdapters, } from "./adapters.js";
|
|
3
|
+
import { evaluateAssetProfile, rankForProfile, toResolveConstraints, } from "./profiles.js";
|
|
4
|
+
import { rankResolveCandidates } from "./scoring.js";
|
|
5
|
+
const { FederatedResolver, isAutoPullable } = assetIndex;
|
|
6
|
+
export function toLine(candidate, profile = "general") {
|
|
7
|
+
const { asset } = candidate;
|
|
8
|
+
const line = {
|
|
9
|
+
id: asset.id,
|
|
10
|
+
source: asset.source,
|
|
11
|
+
title: asset.title,
|
|
12
|
+
license: asset.license.spdx,
|
|
13
|
+
autoPullable: isAutoPullable(asset),
|
|
14
|
+
access: asset.access,
|
|
15
|
+
};
|
|
16
|
+
if (asset.sourcePage)
|
|
17
|
+
line.sourcePage = asset.sourcePage;
|
|
18
|
+
if (profile !== "general") {
|
|
19
|
+
const evaluation = evaluateAssetProfile(asset, profile);
|
|
20
|
+
line.profile = {
|
|
21
|
+
name: profile,
|
|
22
|
+
suitable: evaluation.suitable,
|
|
23
|
+
rejectionReasons: evaluation.rejectionReasons,
|
|
24
|
+
warnings: evaluation.warnings,
|
|
25
|
+
validationHooks: evaluation.validationHooks ?? [],
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
return line;
|
|
29
|
+
}
|
|
30
|
+
export function makeDefaultResolver(adapters, limit) {
|
|
31
|
+
return new FederatedResolver({ adapters, limit });
|
|
32
|
+
}
|
|
33
|
+
export async function runSearch(options) {
|
|
34
|
+
const env = options.env ?? process.env;
|
|
35
|
+
const limit = options.limit ?? 10;
|
|
36
|
+
const adapters = buildSearchAdapters(env);
|
|
37
|
+
const resolver = options.makeResolver
|
|
38
|
+
? options.makeResolver(adapters)
|
|
39
|
+
: makeDefaultResolver(adapters, limit);
|
|
40
|
+
const constraints = toResolveConstraints(options.constraints ?? {}, false);
|
|
41
|
+
const profile = options.constraints?.profile ?? "general";
|
|
42
|
+
const result = await resolver.resolve({
|
|
43
|
+
text: options.query,
|
|
44
|
+
constraints,
|
|
45
|
+
});
|
|
46
|
+
const rankedCandidates = rankResolveCandidates(rankForProfile(result.candidates, profile), {
|
|
47
|
+
query: options.query,
|
|
48
|
+
profile,
|
|
49
|
+
});
|
|
50
|
+
const candidateLines = rankedCandidates.map((candidate) => toLine(candidate, profile));
|
|
51
|
+
const candidates = profile !== "general"
|
|
52
|
+
? candidateLines.filter((candidate) => candidate.profile?.suitable === true)
|
|
53
|
+
: candidateLines;
|
|
54
|
+
const rejectedCandidates = profile !== "general"
|
|
55
|
+
? candidateLines.filter((candidate) => candidate.profile?.suitable !== true)
|
|
56
|
+
: [];
|
|
57
|
+
const anyPullable = candidates.some((c) => c.autoPullable);
|
|
58
|
+
const anyProfileSuitable = profile === "general" || candidates.some((c) => c.profile?.suitable);
|
|
59
|
+
const anyProfilePullable = profile === "general" || candidates.some((c) => c.autoPullable && c.profile?.suitable);
|
|
60
|
+
const warnings = [...result.warnings];
|
|
61
|
+
if (profile !== "general") {
|
|
62
|
+
for (const candidate of candidateLines) {
|
|
63
|
+
for (const warning of candidate.profile?.warnings ?? []) {
|
|
64
|
+
warnings.push(`${candidate.id}: ${warning}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
let deepLinks = [];
|
|
69
|
+
if (!anyPullable) {
|
|
70
|
+
const deepLinkAdapter = buildDeepLinkAdapter();
|
|
71
|
+
if (deepLinkAdapter) {
|
|
72
|
+
try {
|
|
73
|
+
const records = await deepLinkAdapter.search({ text: options.query, constraints: {} }, { fetchJson: assetIndex.defaultFetchJson });
|
|
74
|
+
deepLinks = records.map((asset) => toLine({ asset, score: 0 }));
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
warnings.push(`${deepLinkAdapter.id}: ${err.message}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const messages = [];
|
|
82
|
+
if (candidateLines.length === 0) {
|
|
83
|
+
messages.push(`No candidates found for "${options.query}".`);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
messages.push(`${candidates.length} candidate(s) for "${options.query}" using ${profile} profile.`);
|
|
87
|
+
if (rejectedCandidates.length > 0) {
|
|
88
|
+
messages.push(`${rejectedCandidates.length} rejected candidate(s) moved to rejectedCandidates by the ${profile} profile.`);
|
|
89
|
+
}
|
|
90
|
+
if (!anyPullable) {
|
|
91
|
+
messages.push("No auto-pullable candidate. Listed assets need a manual license check before use.");
|
|
92
|
+
}
|
|
93
|
+
if (profile !== "general" && !anyProfileSuitable) {
|
|
94
|
+
messages.push(`No ${profile}-ready candidate. Listed candidates were rejected by the asset profile; inspect rejectionReasons before resolving.`);
|
|
95
|
+
}
|
|
96
|
+
else if (profile !== "general" && !anyProfilePullable) {
|
|
97
|
+
messages.push(`No auto-pullable ${profile}-ready candidate. Resolve will refuse until a downloadable licensed candidate also passes the profile.`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (deepLinks.length > 0) {
|
|
101
|
+
messages.push(`${deepLinks.length} marketplace deep-link(s) - manual download (license check required).`);
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
ok: true,
|
|
105
|
+
query: options.query,
|
|
106
|
+
profile,
|
|
107
|
+
candidates,
|
|
108
|
+
rejectedCandidates,
|
|
109
|
+
deepLinks,
|
|
110
|
+
warnings,
|
|
111
|
+
messages,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../../../../packages/aura3d-cli/src/pull-bridge/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AnimationAssetProfile } from "@aura3d/asset-index";
|
|
2
|
+
export type CliAssetSearchProfile = "general" | "fighting-character" | AnimationAssetProfile;
|
|
3
|
+
export interface CliResolveConstraints {
|
|
4
|
+
readonly license?: readonly ("CC0" | "CC-BY")[];
|
|
5
|
+
readonly maxTriangles?: number;
|
|
6
|
+
readonly animated?: boolean;
|
|
7
|
+
readonly profile?: CliAssetSearchProfile;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../packages/aura3d-cli/src/pull-bridge/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEjE,MAAM,MAAM,qBAAqB,GAC7B,SAAS,GACT,oBAAoB,GACpB,qBAAqB,CAAC;AAE1B,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,KAAK,GAAG,OAAO,CAAC,EAAE,CAAC;IAChD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,qBAAqB,CAAC;CAC1C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../packages/aura3d-cli/src/pull-bridge/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vector3.d.ts","sourceRoot":"","sources":["../../../../../packages/aura3d-cli/src/pull-bridge/vector3.ts"],"names":[],"mappings":"AAAA,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GACnD,OAAO,CAET"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vector3.js","sourceRoot":"","sources":["../../../../../packages/aura3d-cli/src/pull-bridge/vector3.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,iBAAiB,CAC/B,KAAoD;IAEpD,OAAO,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;AACvF,CAAC"}
|
package/dist/pull-bridge.d.ts
CHANGED
|
@@ -1,104 +1,21 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import { addAsset } from "./index.js";
|
|
1
|
+
import type { FederatedResolver as FederatedResolverType, SourceAdapter } from "@aura3d/asset-index";
|
|
2
|
+
import { addAsset, inspectAsset } from "./index.js";
|
|
3
3
|
import type { AssetCliResult } from "./index.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export
|
|
13
|
-
export type
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
/** Translate CLI flags into the index's ResolveConstraints shape. */
|
|
21
|
-
export declare function toResolveConstraints(cli: CliResolveConstraints, redistributableOnly: boolean): ResolveConstraints;
|
|
22
|
-
/**
|
|
23
|
-
* Pure selection seam: choose the top candidate Aura may legally auto-pull.
|
|
24
|
-
*
|
|
25
|
-
* Returns the first candidate that is downloadable under a verified,
|
|
26
|
-
* redistributable license (`isAutoPullable`). When none qualifies it returns a
|
|
27
|
-
* structured refusal explaining why, so the caller never silently pulls an
|
|
28
|
-
* UNVERIFIED or deep-link-only asset.
|
|
29
|
-
*/
|
|
30
|
-
export interface PullableSelection {
|
|
31
|
-
readonly ok: true;
|
|
32
|
-
readonly candidate: ResolveCandidate;
|
|
33
|
-
}
|
|
34
|
-
export interface PullableRefusal {
|
|
35
|
-
readonly ok: false;
|
|
36
|
-
readonly reason: string;
|
|
37
|
-
}
|
|
38
|
-
export declare function selectPullable(candidates: readonly ResolveCandidate[], options?: {
|
|
39
|
-
readonly profile?: CliAssetSearchProfile;
|
|
40
|
-
}): PullableSelection | PullableRefusal;
|
|
41
|
-
/**
|
|
42
|
-
* Result of a download. A downloader normally writes to the requested
|
|
43
|
-
* `destPath`; when the payload was a ZIP it unpacks into the same directory and
|
|
44
|
-
* returns the assembled artifact's path via `path`. Returning nothing keeps the
|
|
45
|
-
* legacy `(url, destPath) => void` contract (tests rely on this).
|
|
46
|
-
*/
|
|
47
|
-
export interface DownloadResult {
|
|
48
|
-
/** Final on-disk file to feed the add pipeline (defaults to the requested dest). */
|
|
49
|
-
readonly path?: string;
|
|
50
|
-
}
|
|
51
|
-
/** Injected file downloader (overridable for tests). */
|
|
52
|
-
export type DownloadFile = (url: string, destPath: string) => Promise<DownloadResult | void>;
|
|
53
|
-
/**
|
|
54
|
-
* Default downloader backed by global fetch.
|
|
55
|
-
*
|
|
56
|
-
* Objaverse URLs are direct `.glb`; Poly Pizza / Sketchfab artifacts can arrive
|
|
57
|
-
* as a ZIP (gltf + bin + textures, or a packaged .glb). We sniff the leading
|
|
58
|
-
* bytes: a GLB/gltf body is written through as-is; a `PK` body is unpacked next
|
|
59
|
-
* to `destPath` and the assembled .glb/.gltf path is returned. Auth-gated
|
|
60
|
-
* Sketchfab `download` endpoints return JSON (a signed-URL envelope, or a 401);
|
|
61
|
-
* we surface a clear, non-fatal-to-the-tool error instead of writing garbage.
|
|
62
|
-
*/
|
|
63
|
-
export declare const defaultDownloadFile: DownloadFile;
|
|
64
|
-
export interface SearchOptions {
|
|
65
|
-
readonly query: string;
|
|
66
|
-
readonly constraints?: CliResolveConstraints;
|
|
67
|
-
readonly limit?: number;
|
|
68
|
-
readonly env?: NodeJS.ProcessEnv;
|
|
69
|
-
/** Test seam: override resolver construction. */
|
|
70
|
-
readonly makeResolver?: (adapters: readonly SourceAdapter[]) => FederatedResolverType;
|
|
71
|
-
}
|
|
72
|
-
export interface SearchCandidateLine {
|
|
73
|
-
readonly id: string;
|
|
74
|
-
readonly source: string;
|
|
75
|
-
readonly title: string;
|
|
76
|
-
readonly license: string;
|
|
77
|
-
readonly autoPullable: boolean;
|
|
78
|
-
readonly access: AuraCanonicalAsset["access"];
|
|
79
|
-
readonly sourcePage?: string;
|
|
80
|
-
readonly profile?: {
|
|
81
|
-
readonly name: Exclude<CliAssetSearchProfile, "general">;
|
|
82
|
-
readonly suitable: boolean;
|
|
83
|
-
readonly rejectionReasons: readonly string[];
|
|
84
|
-
readonly warnings: readonly string[];
|
|
85
|
-
/** Post-download checks deferred by pre-download ranking (animation profiles). */
|
|
86
|
-
readonly validationHooks: readonly string[];
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
export interface SearchReport {
|
|
90
|
-
readonly ok: boolean;
|
|
91
|
-
readonly query: string;
|
|
92
|
-
readonly profile: CliAssetSearchProfile;
|
|
93
|
-
readonly candidates: readonly SearchCandidateLine[];
|
|
94
|
-
readonly rejectedCandidates: readonly SearchCandidateLine[];
|
|
95
|
-
/** Deep-link discovery suggestions shown only when nothing is auto-pullable. */
|
|
96
|
-
readonly deepLinks: readonly SearchCandidateLine[];
|
|
97
|
-
readonly warnings: readonly string[];
|
|
98
|
-
readonly messages: readonly string[];
|
|
99
|
-
}
|
|
100
|
-
/** Run a federated search and produce a printable report. */
|
|
101
|
-
export declare function runSearch(options: SearchOptions): Promise<SearchReport>;
|
|
4
|
+
import { defaultDownloadFile } from "./pull-bridge/download.js";
|
|
5
|
+
import type { DownloadFile } from "./pull-bridge/download.js";
|
|
6
|
+
import { toResolveConstraints } from "./pull-bridge/profiles.js";
|
|
7
|
+
import { selectPullable } from "./pull-bridge/pullable.js";
|
|
8
|
+
import { rankResolveCandidates, scoreResolveCandidate } from "./pull-bridge/scoring.js";
|
|
9
|
+
import { runSearch } from "./pull-bridge/search.js";
|
|
10
|
+
import type { SearchCandidateLine } from "./pull-bridge/search.js";
|
|
11
|
+
import type { CliAssetSearchProfile, CliResolveConstraints } from "./pull-bridge/types.js";
|
|
12
|
+
export { defaultDownloadFile, rankResolveCandidates, runSearch, selectPullable, scoreResolveCandidate, toResolveConstraints, };
|
|
13
|
+
export type { DownloadFile, DownloadResult } from "./pull-bridge/download.js";
|
|
14
|
+
export type { PullableRefusal, PullableSelection } from "./pull-bridge/pullable.js";
|
|
15
|
+
export type { AssetResolveCandidateScore } from "./pull-bridge/scoring.js";
|
|
16
|
+
export type { SearchCandidateLine, SearchOptions, SearchReport, } from "./pull-bridge/search.js";
|
|
17
|
+
export type { CliAssetSearchProfile, CliResolveConstraints, } from "./pull-bridge/types.js";
|
|
18
|
+
export { buildDeepLinkAdapter, buildSearchAdapters } from "./pull-bridge/adapters.js";
|
|
102
19
|
export interface ResolveOptions {
|
|
103
20
|
readonly query: string;
|
|
104
21
|
readonly name: string;
|
|
@@ -109,6 +26,7 @@ export interface ResolveOptions {
|
|
|
109
26
|
readonly makeResolver?: (adapters: readonly SourceAdapter[]) => FederatedResolverType;
|
|
110
27
|
readonly download?: DownloadFile;
|
|
111
28
|
readonly addAssetFn?: typeof addAsset;
|
|
29
|
+
readonly inspectAssetFn?: typeof inspectAsset;
|
|
112
30
|
readonly tmpRoot?: string;
|
|
113
31
|
/**
|
|
114
32
|
* Retrieval timestamp recorded in provenance. Injectable so deterministic
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull-bridge.d.ts","sourceRoot":"","sources":["../../../../packages/aura3d-cli/src/pull-bridge.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EACV,
|
|
1
|
+
{"version":3,"file":"pull-bridge.d.ts","sourceRoot":"","sources":["../../../../packages/aura3d-cli/src/pull-bridge.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EACV,iBAAiB,IAAI,qBAAqB,EAC1C,aAAa,EACd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,KAAK,EACV,cAAc,EAEf,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAGL,oBAAoB,EACrB,MAAM,2BAA2B,CAAC;AAOnC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAEL,SAAS,EAEV,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EACV,qBAAqB,EACrB,qBAAqB,EACtB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,SAAS,EACT,cAAc,EACd,qBAAqB,EACrB,oBAAoB,GACrB,CAAC;AACF,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC9E,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACpF,YAAY,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAC3E,YAAY,EACV,mBAAmB,EACnB,aAAa,EACb,YAAY,GACb,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAIhC,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEtF,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,CAAC,EAAE,qBAAqB,CAAC;IAC7C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,kBAAkB;IAClB,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,KAAK,qBAAqB,CAAC;IACtF,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,QAAQ,CAAC;IACtC,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,YAAY,CAAC;IAC9C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,qBAAqB,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,mBAAmB,CAAC;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,cAAc,CAAC;CAC/B;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAoJhF"}
|