@ubiquity-os/plugin-sdk 3.6.3 → 3.7.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/configuration.d.mts +16 -11
- package/dist/configuration.d.ts +16 -11
- package/dist/configuration.js +219 -36
- package/dist/configuration.mjs +219 -36
- package/dist/{context-BbEmsEct.d.ts → context-BE4WjJZf.d.ts} +1 -0
- package/dist/{context-sqbr2o6i.d.mts → context-Ckj1HMjz.d.mts} +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +209 -124
- package/dist/index.mjs +209 -124
- package/dist/llm.d.mts +1 -1
- package/dist/llm.d.ts +1 -1
- package/dist/llm.js +46 -11
- package/dist/llm.mjs +46 -11
- package/dist/signature.js +2 -2
- package/dist/signature.mjs +2 -2
- package/package.json +1 -1
package/dist/configuration.mjs
CHANGED
|
@@ -2707,14 +2707,101 @@ var manifestSchema = T2.Object({
|
|
|
2707
2707
|
var CONFIG_PROD_FULL_PATH = ".github/.ubiquity-os.config.yml";
|
|
2708
2708
|
var CONFIG_DEV_FULL_PATH = ".github/.ubiquity-os.config.dev.yml";
|
|
2709
2709
|
var CONFIG_ORG_REPO = ".ubiquity-os";
|
|
2710
|
+
var ENVIRONMENT_TO_CONFIG_SUFFIX = {
|
|
2711
|
+
development: "dev"
|
|
2712
|
+
};
|
|
2713
|
+
var VALID_CONFIG_SUFFIX = /^[a-z0-9][a-z0-9_-]*$/i;
|
|
2714
|
+
var MAX_IMPORT_DEPTH = 6;
|
|
2715
|
+
function normalizeEnvironmentName(environment) {
|
|
2716
|
+
return String(environment ?? "").trim().toLowerCase();
|
|
2717
|
+
}
|
|
2718
|
+
function getConfigPathCandidatesForEnvironment(environment) {
|
|
2719
|
+
const normalized = normalizeEnvironmentName(environment);
|
|
2720
|
+
if (!normalized) {
|
|
2721
|
+
return [CONFIG_PROD_FULL_PATH, CONFIG_DEV_FULL_PATH];
|
|
2722
|
+
}
|
|
2723
|
+
if (normalized === "production" || normalized === "prod") {
|
|
2724
|
+
return [CONFIG_PROD_FULL_PATH];
|
|
2725
|
+
}
|
|
2726
|
+
const suffix = ENVIRONMENT_TO_CONFIG_SUFFIX[normalized] ?? normalized;
|
|
2727
|
+
if (suffix === "dev") {
|
|
2728
|
+
return [CONFIG_DEV_FULL_PATH];
|
|
2729
|
+
}
|
|
2730
|
+
if (!VALID_CONFIG_SUFFIX.test(suffix)) {
|
|
2731
|
+
return [CONFIG_DEV_FULL_PATH];
|
|
2732
|
+
}
|
|
2733
|
+
return [`.github/.ubiquity-os.config.${suffix}.yml`, CONFIG_PROD_FULL_PATH];
|
|
2734
|
+
}
|
|
2735
|
+
function normalizeImportKey(location) {
|
|
2736
|
+
return `${location.owner}`.trim().toLowerCase() + "/" + `${location.repo}`.trim().toLowerCase();
|
|
2737
|
+
}
|
|
2738
|
+
function parseImportSpec(value) {
|
|
2739
|
+
const trimmed = value.trim();
|
|
2740
|
+
if (!trimmed) return null;
|
|
2741
|
+
const parts = trimmed.split("/");
|
|
2742
|
+
if (parts.length !== 2) return null;
|
|
2743
|
+
const [owner, repo] = parts;
|
|
2744
|
+
if (!owner || !repo) return null;
|
|
2745
|
+
return { owner, repo };
|
|
2746
|
+
}
|
|
2747
|
+
function readImports(logger, value, source) {
|
|
2748
|
+
if (!value) return [];
|
|
2749
|
+
if (!Array.isArray(value)) {
|
|
2750
|
+
logger.warn("Invalid imports; expected a list of strings.", { source });
|
|
2751
|
+
return [];
|
|
2752
|
+
}
|
|
2753
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2754
|
+
const imports = [];
|
|
2755
|
+
for (const entry of value) {
|
|
2756
|
+
if (typeof entry !== "string") {
|
|
2757
|
+
logger.warn("Ignoring invalid import entry; expected string.", { source, entry });
|
|
2758
|
+
continue;
|
|
2759
|
+
}
|
|
2760
|
+
const parsed = parseImportSpec(entry);
|
|
2761
|
+
if (!parsed) {
|
|
2762
|
+
logger.warn("Ignoring invalid import entry; expected owner/repo.", { source, entry });
|
|
2763
|
+
continue;
|
|
2764
|
+
}
|
|
2765
|
+
const key = normalizeImportKey(parsed);
|
|
2766
|
+
if (seen.has(key)) continue;
|
|
2767
|
+
seen.add(key);
|
|
2768
|
+
imports.push(parsed);
|
|
2769
|
+
}
|
|
2770
|
+
return imports;
|
|
2771
|
+
}
|
|
2772
|
+
function stripImports(config) {
|
|
2773
|
+
if (!config || typeof config !== "object") return config;
|
|
2774
|
+
const { imports: _imports, ...rest } = config;
|
|
2775
|
+
return rest;
|
|
2776
|
+
}
|
|
2777
|
+
function mergeImportedConfigs(imported, base) {
|
|
2778
|
+
if (!imported.length) {
|
|
2779
|
+
return base;
|
|
2780
|
+
}
|
|
2781
|
+
let merged = imported[0];
|
|
2782
|
+
for (let i = 1; i < imported.length; i++) {
|
|
2783
|
+
merged = {
|
|
2784
|
+
...merged,
|
|
2785
|
+
...imported[i],
|
|
2786
|
+
plugins: { ...merged.plugins, ...imported[i].plugins }
|
|
2787
|
+
};
|
|
2788
|
+
}
|
|
2789
|
+
return base ? {
|
|
2790
|
+
...merged,
|
|
2791
|
+
...base,
|
|
2792
|
+
plugins: { ...merged.plugins, ...base.plugins }
|
|
2793
|
+
} : merged;
|
|
2794
|
+
}
|
|
2710
2795
|
var ConfigurationHandler = class {
|
|
2711
|
-
constructor(_logger, _octokit, _environment = null) {
|
|
2796
|
+
constructor(_logger, _octokit, _environment = null, options) {
|
|
2712
2797
|
this._logger = _logger;
|
|
2713
2798
|
this._octokit = _octokit;
|
|
2714
2799
|
this._environment = _environment;
|
|
2800
|
+
this._octokitFactory = options?.octokitFactory;
|
|
2715
2801
|
}
|
|
2716
2802
|
_manifestCache = {};
|
|
2717
2803
|
_manifestPromiseCache = {};
|
|
2804
|
+
_octokitFactory;
|
|
2718
2805
|
/**
|
|
2719
2806
|
* Retrieves the configuration for the current plugin based on its manifest.
|
|
2720
2807
|
* @param manifest - The plugin manifest containing the `short_name` identifier
|
|
@@ -2733,7 +2820,7 @@ var ConfigurationHandler = class {
|
|
|
2733
2820
|
* @returns The merged plugin configuration with resolved plugin settings.
|
|
2734
2821
|
*/
|
|
2735
2822
|
async getConfiguration(location) {
|
|
2736
|
-
const defaultConfiguration = Value.Decode(configSchema, Value.Default(configSchema, {}));
|
|
2823
|
+
const defaultConfiguration = stripImports(Value.Decode(configSchema, Value.Default(configSchema, {})));
|
|
2737
2824
|
if (!location) {
|
|
2738
2825
|
this._logger.info("No location was provided, using the default configuration");
|
|
2739
2826
|
return defaultConfiguration;
|
|
@@ -2794,57 +2881,153 @@ var ConfigurationHandler = class {
|
|
|
2794
2881
|
* @param repository The repository name
|
|
2795
2882
|
*/
|
|
2796
2883
|
async getConfigurationFromRepo(owner, repository) {
|
|
2884
|
+
const location = { owner, repo: repository };
|
|
2885
|
+
const state = this._createImportState();
|
|
2886
|
+
const octokit = await this._getOctokitForLocation(location, state);
|
|
2887
|
+
if (!octokit) {
|
|
2888
|
+
this._logger.warn("No Octokit available for configuration load", { owner, repository });
|
|
2889
|
+
return { config: null, errors: null, rawData: null };
|
|
2890
|
+
}
|
|
2891
|
+
const { config, imports, errors, rawData } = await this._loadConfigSource(location, octokit);
|
|
2892
|
+
if (!rawData) {
|
|
2893
|
+
return { config: null, errors: null, rawData: null };
|
|
2894
|
+
}
|
|
2895
|
+
if (errors && errors.length) {
|
|
2896
|
+
this._logger.warn("YAML could not be decoded", { owner, repository, errors });
|
|
2897
|
+
return { config: null, errors, rawData };
|
|
2898
|
+
}
|
|
2899
|
+
if (!config) {
|
|
2900
|
+
this._logger.warn("YAML could not be decoded", { owner, repository });
|
|
2901
|
+
return { config: null, errors, rawData };
|
|
2902
|
+
}
|
|
2903
|
+
const importedConfigs = [];
|
|
2904
|
+
for (const next of imports) {
|
|
2905
|
+
const resolved = await this._resolveImportedConfiguration(next, state, 1);
|
|
2906
|
+
if (resolved) importedConfigs.push(resolved);
|
|
2907
|
+
}
|
|
2908
|
+
const mergedConfig = mergeImportedConfigs(importedConfigs, config);
|
|
2909
|
+
if (!mergedConfig) {
|
|
2910
|
+
return { config: null, errors: null, rawData };
|
|
2911
|
+
}
|
|
2912
|
+
const decoded = this._decodeConfiguration(location, mergedConfig);
|
|
2913
|
+
return { config: decoded.config, errors: decoded.errors, rawData };
|
|
2914
|
+
}
|
|
2915
|
+
_createImportState() {
|
|
2916
|
+
return {
|
|
2917
|
+
cache: /* @__PURE__ */ new Map(),
|
|
2918
|
+
inFlight: /* @__PURE__ */ new Set(),
|
|
2919
|
+
octokitByLocation: /* @__PURE__ */ new Map()
|
|
2920
|
+
};
|
|
2921
|
+
}
|
|
2922
|
+
async _getOctokitForLocation(location, state) {
|
|
2923
|
+
const key = normalizeImportKey(location);
|
|
2924
|
+
if (state.octokitByLocation.has(key)) {
|
|
2925
|
+
return state.octokitByLocation.get(key) ?? null;
|
|
2926
|
+
}
|
|
2927
|
+
if (this._octokitFactory) {
|
|
2928
|
+
const resolved = await this._octokitFactory(location);
|
|
2929
|
+
if (resolved) {
|
|
2930
|
+
state.octokitByLocation.set(key, resolved);
|
|
2931
|
+
return resolved;
|
|
2932
|
+
}
|
|
2933
|
+
}
|
|
2934
|
+
state.octokitByLocation.set(key, this._octokit);
|
|
2935
|
+
return this._octokit;
|
|
2936
|
+
}
|
|
2937
|
+
async _loadConfigSource(location, octokit) {
|
|
2797
2938
|
const rawData = await this._download({
|
|
2798
|
-
repository,
|
|
2799
|
-
owner
|
|
2939
|
+
repository: location.repo,
|
|
2940
|
+
owner: location.owner,
|
|
2941
|
+
octokit
|
|
2800
2942
|
});
|
|
2801
|
-
this._logger.ok("Downloaded configuration file", { owner, repository });
|
|
2943
|
+
this._logger.ok("Downloaded configuration file", { owner: location.owner, repository: location.repo });
|
|
2802
2944
|
if (!rawData) {
|
|
2803
|
-
this._logger.warn("No raw configuration data", { owner, repository });
|
|
2804
|
-
return { config: null, errors: null, rawData: null };
|
|
2945
|
+
this._logger.warn("No raw configuration data", { owner: location.owner, repository: location.repo });
|
|
2946
|
+
return { config: null, imports: [], errors: null, rawData: null };
|
|
2805
2947
|
}
|
|
2806
2948
|
const { yaml, errors } = this._parseYaml(rawData);
|
|
2949
|
+
const imports = readImports(this._logger, yaml?.imports, location);
|
|
2950
|
+
if (yaml && typeof yaml === "object" && !Array.isArray(yaml) && "imports" in yaml) {
|
|
2951
|
+
delete yaml.imports;
|
|
2952
|
+
}
|
|
2807
2953
|
const targetRepoConfiguration = yaml;
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2954
|
+
return { config: targetRepoConfiguration, imports, errors, rawData };
|
|
2955
|
+
}
|
|
2956
|
+
_decodeConfiguration(location, config) {
|
|
2957
|
+
this._logger.info("Decoding configuration", { owner: location.owner, repository: location.repo });
|
|
2958
|
+
try {
|
|
2959
|
+
const configSchemaWithDefaults = Value.Default(configSchema, config);
|
|
2960
|
+
const errors = Value.Errors(configSchema, configSchemaWithDefaults);
|
|
2961
|
+
if (errors.First()) {
|
|
2962
|
+
for (const error of errors) {
|
|
2963
|
+
this._logger.warn("Configuration validation error", { err: error });
|
|
2817
2964
|
}
|
|
2818
|
-
const decodedConfig = Value.Decode(configSchema, configSchemaWithDefaults);
|
|
2819
|
-
return { config: decodedConfig, errors: errors2.First() ? errors2 : null, rawData };
|
|
2820
|
-
} catch (error) {
|
|
2821
|
-
this._logger.warn("Error decoding configuration; Will ignore.", { err: error, owner, repository });
|
|
2822
|
-
return { config: null, errors: [error instanceof TransformDecodeCheckError ? error.error : error], rawData };
|
|
2823
2965
|
}
|
|
2966
|
+
const decodedConfig = Value.Decode(configSchema, configSchemaWithDefaults);
|
|
2967
|
+
return { config: stripImports(decodedConfig), errors: errors.First() ? errors : null };
|
|
2968
|
+
} catch (error) {
|
|
2969
|
+
this._logger.warn("Error decoding configuration; Will ignore.", { err: error, owner: location.owner, repository: location.repo });
|
|
2970
|
+
return { config: null, errors: [error instanceof TransformDecodeCheckError ? error.error : error] };
|
|
2824
2971
|
}
|
|
2825
|
-
this._logger.warn("YAML could not be decoded", { owner, repository, errors });
|
|
2826
|
-
return { config: null, errors, rawData };
|
|
2827
2972
|
}
|
|
2828
|
-
async
|
|
2973
|
+
async _resolveImportedConfiguration(location, state, depth) {
|
|
2974
|
+
const key = normalizeImportKey(location);
|
|
2975
|
+
if (state.cache.has(key)) {
|
|
2976
|
+
return state.cache.get(key) ?? null;
|
|
2977
|
+
}
|
|
2978
|
+
if (state.inFlight.has(key)) {
|
|
2979
|
+
this._logger.warn("Skipping import due to circular reference.", { location });
|
|
2980
|
+
return null;
|
|
2981
|
+
}
|
|
2982
|
+
if (depth > MAX_IMPORT_DEPTH) {
|
|
2983
|
+
this._logger.warn("Skipping import; maximum depth exceeded.", { location, depth });
|
|
2984
|
+
return null;
|
|
2985
|
+
}
|
|
2986
|
+
state.inFlight.add(key);
|
|
2987
|
+
let resolved = null;
|
|
2988
|
+
try {
|
|
2989
|
+
const octokit = await this._getOctokitForLocation(location, state);
|
|
2990
|
+
if (!octokit) {
|
|
2991
|
+
this._logger.warn("Skipping import; no authorized Octokit for owner.", { location });
|
|
2992
|
+
return null;
|
|
2993
|
+
}
|
|
2994
|
+
const { config, imports, errors } = await this._loadConfigSource(location, octokit);
|
|
2995
|
+
if (errors && errors.length) {
|
|
2996
|
+
this._logger.warn("Skipping import due to YAML parsing errors.", { location, errors });
|
|
2997
|
+
return null;
|
|
2998
|
+
}
|
|
2999
|
+
if (!config) {
|
|
3000
|
+
return null;
|
|
3001
|
+
}
|
|
3002
|
+
const importedConfigs = [];
|
|
3003
|
+
for (const next of imports) {
|
|
3004
|
+
const nested = await this._resolveImportedConfiguration(next, state, depth + 1);
|
|
3005
|
+
if (nested) importedConfigs.push(nested);
|
|
3006
|
+
}
|
|
3007
|
+
const mergedConfig = mergeImportedConfigs(importedConfigs, config);
|
|
3008
|
+
if (!mergedConfig) return null;
|
|
3009
|
+
const decoded = this._decodeConfiguration(location, mergedConfig);
|
|
3010
|
+
resolved = decoded.config;
|
|
3011
|
+
} finally {
|
|
3012
|
+
state.inFlight.delete(key);
|
|
3013
|
+
state.cache.set(key, resolved);
|
|
3014
|
+
}
|
|
3015
|
+
return resolved;
|
|
3016
|
+
}
|
|
3017
|
+
async _download({
|
|
3018
|
+
repository,
|
|
3019
|
+
owner,
|
|
3020
|
+
octokit
|
|
3021
|
+
}) {
|
|
2829
3022
|
if (!repository || !owner) {
|
|
2830
3023
|
this._logger.warn("Repo or owner is not defined, cannot download the requested file");
|
|
2831
3024
|
return null;
|
|
2832
3025
|
}
|
|
2833
|
-
|
|
2834
|
-
switch (this._environment) {
|
|
2835
|
-
case "development":
|
|
2836
|
-
pathList = [CONFIG_DEV_FULL_PATH];
|
|
2837
|
-
break;
|
|
2838
|
-
case "production":
|
|
2839
|
-
pathList = [CONFIG_PROD_FULL_PATH];
|
|
2840
|
-
break;
|
|
2841
|
-
default:
|
|
2842
|
-
pathList = [CONFIG_PROD_FULL_PATH, CONFIG_DEV_FULL_PATH];
|
|
2843
|
-
}
|
|
3026
|
+
const pathList = getConfigPathCandidatesForEnvironment(this._environment);
|
|
2844
3027
|
for (const filePath of pathList) {
|
|
2845
3028
|
try {
|
|
2846
3029
|
this._logger.info("Attempting to fetch configuration", { owner, repository, filePath });
|
|
2847
|
-
const { data, headers } = await
|
|
3030
|
+
const { data, headers } = await octokit.rest.repos.getContent({
|
|
2848
3031
|
owner,
|
|
2849
3032
|
repo: repository,
|
|
2850
3033
|
path: filePath,
|
|
@@ -45,6 +45,7 @@ declare class CommentHandler {
|
|
|
45
45
|
_extractIssueContext(context: Context): IssueContext | null;
|
|
46
46
|
_processMessage(context: Context, message: LogReturn | Error): {
|
|
47
47
|
metadata: {
|
|
48
|
+
status?: number | undefined;
|
|
48
49
|
message: string;
|
|
49
50
|
name: string;
|
|
50
51
|
stack: string | undefined;
|
|
@@ -45,6 +45,7 @@ declare class CommentHandler {
|
|
|
45
45
|
_extractIssueContext(context: Context): IssueContext | null;
|
|
46
46
|
_processMessage(context: Context, message: LogReturn | Error): {
|
|
47
47
|
metadata: {
|
|
48
|
+
status?: number | undefined;
|
|
48
49
|
message: string;
|
|
49
50
|
name: string;
|
|
50
51
|
stack: string | undefined;
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EmitterWebhookEventName } from '@octokit/webhooks';
|
|
2
|
-
import { C as Context } from './context-
|
|
3
|
-
export { a as CommentHandler } from './context-
|
|
2
|
+
import { C as Context } from './context-Ckj1HMjz.mjs';
|
|
3
|
+
export { a as CommentHandler } from './context-Ckj1HMjz.mjs';
|
|
4
4
|
import { TSchema, TAnySchema } from '@sinclair/typebox';
|
|
5
5
|
import { LogLevel } from '@ubiquity-os/ubiquity-os-logger';
|
|
6
6
|
import * as hono_types from 'hono/types';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EmitterWebhookEventName } from '@octokit/webhooks';
|
|
2
|
-
import { C as Context } from './context-
|
|
3
|
-
export { a as CommentHandler } from './context-
|
|
2
|
+
import { C as Context } from './context-BE4WjJZf.js';
|
|
3
|
+
export { a as CommentHandler } from './context-BE4WjJZf.js';
|
|
4
4
|
import { TSchema, TAnySchema } from '@sinclair/typebox';
|
|
5
5
|
import { LogLevel } from '@ubiquity-os/ubiquity-os-logger';
|
|
6
6
|
import * as hono_types from 'hono/types';
|