@ubiquity-os/plugin-sdk 3.8.1 → 3.8.4

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.
@@ -15,7 +15,7 @@ function parsePluginIdentifier(value) {
15
15
  return {
16
16
  owner: matches[1],
17
17
  repo: matches[2],
18
- workflowId: matches[3] || "dispatch.yml",
18
+ workflowId: matches[3] || "compute.yml",
19
19
  ref: matches[4] || void 0
20
20
  };
21
21
  }
@@ -41,7 +41,6 @@ var pluginSettingsSchema = T.Union(
41
41
  );
42
42
  var configSchema = T.Object(
43
43
  {
44
- imports: T.Optional(T.Array(T.String(), { default: [] })),
45
44
  plugins: T.Record(T.String(), pluginSettingsSchema, { default: {} })
46
45
  },
47
46
  {
@@ -82,101 +81,14 @@ var manifestSchema = T2.Object({
82
81
  var CONFIG_PROD_FULL_PATH = ".github/.ubiquity-os.config.yml";
83
82
  var CONFIG_DEV_FULL_PATH = ".github/.ubiquity-os.config.dev.yml";
84
83
  var CONFIG_ORG_REPO = ".ubiquity-os";
85
- var ENVIRONMENT_TO_CONFIG_SUFFIX = {
86
- development: "dev"
87
- };
88
- var VALID_CONFIG_SUFFIX = /^[a-z0-9][a-z0-9_-]*$/i;
89
- var MAX_IMPORT_DEPTH = 6;
90
- function normalizeEnvironmentName(environment) {
91
- return String(environment ?? "").trim().toLowerCase();
92
- }
93
- function getConfigPathCandidatesForEnvironment(environment) {
94
- const normalized = normalizeEnvironmentName(environment);
95
- if (!normalized) {
96
- return [CONFIG_PROD_FULL_PATH, CONFIG_DEV_FULL_PATH];
97
- }
98
- if (normalized === "production" || normalized === "prod") {
99
- return [CONFIG_PROD_FULL_PATH];
100
- }
101
- const suffix = ENVIRONMENT_TO_CONFIG_SUFFIX[normalized] ?? normalized;
102
- if (suffix === "dev") {
103
- return [CONFIG_DEV_FULL_PATH];
104
- }
105
- if (!VALID_CONFIG_SUFFIX.test(suffix)) {
106
- return [CONFIG_DEV_FULL_PATH];
107
- }
108
- return [`.github/.ubiquity-os.config.${suffix}.yml`, CONFIG_PROD_FULL_PATH];
109
- }
110
- function normalizeImportKey(location) {
111
- return `${location.owner}`.trim().toLowerCase() + "/" + `${location.repo}`.trim().toLowerCase();
112
- }
113
- function parseImportSpec(value) {
114
- const trimmed = value.trim();
115
- if (!trimmed) return null;
116
- const parts = trimmed.split("/");
117
- if (parts.length !== 2) return null;
118
- const [owner, repo] = parts;
119
- if (!owner || !repo) return null;
120
- return { owner, repo };
121
- }
122
- function readImports(logger, value, source) {
123
- if (!value) return [];
124
- if (!Array.isArray(value)) {
125
- logger.warn("Invalid imports; expected a list of strings.", { source });
126
- return [];
127
- }
128
- const seen = /* @__PURE__ */ new Set();
129
- const imports = [];
130
- for (const entry of value) {
131
- if (typeof entry !== "string") {
132
- logger.warn("Ignoring invalid import entry; expected string.", { source, entry });
133
- continue;
134
- }
135
- const parsed = parseImportSpec(entry);
136
- if (!parsed) {
137
- logger.warn("Ignoring invalid import entry; expected owner/repo.", { source, entry });
138
- continue;
139
- }
140
- const key = normalizeImportKey(parsed);
141
- if (seen.has(key)) continue;
142
- seen.add(key);
143
- imports.push(parsed);
144
- }
145
- return imports;
146
- }
147
- function stripImports(config) {
148
- if (!config || typeof config !== "object") return config;
149
- const { imports: _imports, ...rest } = config;
150
- return rest;
151
- }
152
- function mergeImportedConfigs(imported, base) {
153
- if (!imported.length) {
154
- return base;
155
- }
156
- let merged = imported[0];
157
- for (let i = 1; i < imported.length; i++) {
158
- merged = {
159
- ...merged,
160
- ...imported[i],
161
- plugins: { ...merged.plugins, ...imported[i].plugins }
162
- };
163
- }
164
- return base ? {
165
- ...merged,
166
- ...base,
167
- plugins: { ...merged.plugins, ...base.plugins }
168
- } : merged;
169
- }
170
84
  var ConfigurationHandler = class {
171
- constructor(_logger, _octokit, _environment = null, options) {
85
+ constructor(_logger, _octokit, _environment = null) {
172
86
  this._logger = _logger;
173
87
  this._octokit = _octokit;
174
88
  this._environment = _environment;
175
- this._octokitFactory = options?.octokitFactory;
176
89
  }
177
90
  _manifestCache = {};
178
91
  _manifestPromiseCache = {};
179
- _octokitFactory;
180
92
  /**
181
93
  * Retrieves the configuration for the current plugin based on its manifest.
182
94
  * @param manifest - The plugin manifest containing the `short_name` identifier
@@ -195,14 +107,14 @@ var ConfigurationHandler = class {
195
107
  * @returns The merged plugin configuration with resolved plugin settings.
196
108
  */
197
109
  async getConfiguration(location) {
198
- const defaultConfiguration = stripImports(Value.Decode(configSchema, Value.Default(configSchema, {})));
110
+ const defaultConfiguration = Value.Decode(configSchema, Value.Default(configSchema, {}));
199
111
  if (!location) {
200
- this._logger.info("No location was provided, using the default configuration");
112
+ this._logger.debug("No location was provided, using the default configuration");
201
113
  return defaultConfiguration;
202
114
  }
203
115
  const { owner, repo } = location;
204
116
  let mergedConfiguration = defaultConfiguration;
205
- this._logger.info("Fetching configurations from the organization and repository", {
117
+ this._logger.debug("Fetching configurations from the organization and repository", {
206
118
  orgRepo: `${owner}/${CONFIG_ORG_REPO}`,
207
119
  repo: `${owner}/${repo}`
208
120
  });
@@ -215,13 +127,13 @@ var ConfigurationHandler = class {
215
127
  mergedConfiguration = this.mergeConfigurations(mergedConfiguration, repoConfig.config);
216
128
  }
217
129
  const resolvedPlugins = {};
218
- this._logger.ok("Found plugins enabled", { repo: `${owner}/${repo}`, plugins: Object.keys(mergedConfiguration.plugins).length });
130
+ this._logger.debug("Found plugins enabled", { repo: `${owner}/${repo}`, plugins: Object.keys(mergedConfiguration.plugins).length });
219
131
  for (const [pluginKey, pluginSettings] of Object.entries(mergedConfiguration.plugins)) {
220
132
  let pluginIdentifier;
221
133
  try {
222
134
  pluginIdentifier = parsePluginIdentifier(pluginKey);
223
135
  } catch (error) {
224
- this._logger.warn("Invalid plugin identifier; skipping", { plugin: pluginKey, err: error });
136
+ this._logger.error("Invalid plugin identifier; skipping", { plugin: pluginKey, err: error });
225
137
  continue;
226
138
  }
227
139
  const manifest = await this.getManifest(pluginIdentifier);
@@ -256,189 +168,87 @@ var ConfigurationHandler = class {
256
168
  * @param repository The repository name
257
169
  */
258
170
  async getConfigurationFromRepo(owner, repository) {
259
- const location = { owner, repo: repository };
260
- const state = this._createImportState();
261
- const octokit = await this._getOctokitForLocation(location, state);
262
- if (!octokit) {
263
- this._logger.warn("No Octokit available for configuration load", { owner, repository });
264
- return { config: null, errors: null, rawData: null };
265
- }
266
- const { config, imports, errors, rawData } = await this._loadConfigSource(location, octokit);
267
- if (!rawData) {
268
- return { config: null, errors: null, rawData: null };
269
- }
270
- if (errors && errors.length) {
271
- this._logger.warn("YAML could not be decoded", { owner, repository, errors });
272
- return { config: null, errors, rawData };
273
- }
274
- if (!config) {
275
- this._logger.warn("YAML could not be decoded", { owner, repository });
276
- return { config: null, errors, rawData };
277
- }
278
- const importedConfigs = [];
279
- for (const next of imports) {
280
- const resolved = await this._resolveImportedConfiguration(next, state, 1);
281
- if (resolved) importedConfigs.push(resolved);
282
- }
283
- const mergedConfig = mergeImportedConfigs(importedConfigs, config);
284
- if (!mergedConfig) {
285
- return { config: null, errors: null, rawData };
286
- }
287
- const decoded = this._decodeConfiguration(location, mergedConfig);
288
- return { config: decoded.config, errors: decoded.errors, rawData };
289
- }
290
- _createImportState() {
291
- return {
292
- cache: /* @__PURE__ */ new Map(),
293
- inFlight: /* @__PURE__ */ new Set(),
294
- octokitByLocation: /* @__PURE__ */ new Map()
295
- };
296
- }
297
- async _getOctokitForLocation(location, state) {
298
- const key = normalizeImportKey(location);
299
- if (state.octokitByLocation.has(key)) {
300
- return state.octokitByLocation.get(key) ?? null;
301
- }
302
- if (this._octokitFactory) {
303
- const resolved = await this._octokitFactory(location);
304
- if (resolved) {
305
- state.octokitByLocation.set(key, resolved);
306
- return resolved;
307
- }
308
- }
309
- state.octokitByLocation.set(key, this._octokit);
310
- return this._octokit;
311
- }
312
- async _loadConfigSource(location, octokit) {
313
171
  const rawData = await this._download({
314
- repository: location.repo,
315
- owner: location.owner,
316
- octokit
172
+ repository,
173
+ owner
317
174
  });
318
- this._logger.ok("Downloaded configuration file", { owner: location.owner, repository: location.repo });
175
+ this._logger.debug("Downloaded configuration file", { owner, repository });
319
176
  if (!rawData) {
320
- this._logger.warn("No raw configuration data", { owner: location.owner, repository: location.repo });
321
- return { config: null, imports: [], errors: null, rawData: null };
177
+ this._logger.debug("No raw configuration data", { owner, repository });
178
+ return { config: null, errors: null, rawData: null };
322
179
  }
323
180
  const { yaml, errors } = this._parseYaml(rawData);
324
- const imports = readImports(this._logger, yaml?.imports, location);
325
- if (yaml && typeof yaml === "object" && !Array.isArray(yaml) && "imports" in yaml) {
326
- delete yaml.imports;
327
- }
328
181
  const targetRepoConfiguration = yaml;
329
- return { config: targetRepoConfiguration, imports, errors, rawData };
330
- }
331
- _decodeConfiguration(location, config) {
332
- this._logger.info("Decoding configuration", { owner: location.owner, repository: location.repo });
333
- try {
334
- const configSchemaWithDefaults = Value.Default(configSchema, config);
335
- const errors = Value.Errors(configSchema, configSchemaWithDefaults);
336
- if (errors.First()) {
337
- for (const error of errors) {
338
- this._logger.warn("Configuration validation error", { err: error });
182
+ this._logger.debug("Decoding configuration", { owner, repository });
183
+ if (targetRepoConfiguration) {
184
+ try {
185
+ const configSchemaWithDefaults = Value.Default(configSchema, targetRepoConfiguration);
186
+ const errors2 = Value.Errors(configSchema, configSchemaWithDefaults);
187
+ if (errors2.First()) {
188
+ for (const error of errors2) {
189
+ this._logger.warn("Configuration validation error", { err: error });
190
+ }
339
191
  }
192
+ const decodedConfig = Value.Decode(configSchema, configSchemaWithDefaults);
193
+ return { config: decodedConfig, errors: errors2.First() ? errors2 : null, rawData };
194
+ } catch (error) {
195
+ this._logger.error("Error decoding configuration; Will ignore.", { err: error, owner, repository });
196
+ return { config: null, errors: [error instanceof TransformDecodeCheckError ? error.error : error], rawData };
340
197
  }
341
- const decodedConfig = Value.Decode(configSchema, configSchemaWithDefaults);
342
- return { config: stripImports(decodedConfig), errors: errors.First() ? errors : null };
343
- } catch (error) {
344
- this._logger.warn("Error decoding configuration; Will ignore.", { err: error, owner: location.owner, repository: location.repo });
345
- return { config: null, errors: [error instanceof TransformDecodeCheckError ? error.error : error] };
346
- }
347
- }
348
- async _resolveImportedConfiguration(location, state, depth) {
349
- const key = normalizeImportKey(location);
350
- if (state.cache.has(key)) {
351
- return state.cache.get(key) ?? null;
352
- }
353
- if (state.inFlight.has(key)) {
354
- this._logger.warn("Skipping import due to circular reference.", { location });
355
- return null;
356
- }
357
- if (depth > MAX_IMPORT_DEPTH) {
358
- this._logger.warn("Skipping import; maximum depth exceeded.", { location, depth });
359
- return null;
360
- }
361
- state.inFlight.add(key);
362
- let resolved = null;
363
- try {
364
- const octokit = await this._getOctokitForLocation(location, state);
365
- if (!octokit) {
366
- this._logger.warn("Skipping import; no authorized Octokit for owner.", { location });
367
- return null;
368
- }
369
- const { config, imports, errors } = await this._loadConfigSource(location, octokit);
370
- if (errors && errors.length) {
371
- this._logger.warn("Skipping import due to YAML parsing errors.", { location, errors });
372
- return null;
373
- }
374
- if (!config) {
375
- return null;
376
- }
377
- const importedConfigs = [];
378
- for (const next of imports) {
379
- const nested = await this._resolveImportedConfiguration(next, state, depth + 1);
380
- if (nested) importedConfigs.push(nested);
381
- }
382
- const mergedConfig = mergeImportedConfigs(importedConfigs, config);
383
- if (!mergedConfig) return null;
384
- const decoded = this._decodeConfiguration(location, mergedConfig);
385
- resolved = decoded.config;
386
- } finally {
387
- state.inFlight.delete(key);
388
- state.cache.set(key, resolved);
389
198
  }
390
- return resolved;
199
+ this._logger.error("YAML could not be decoded", { owner, repository, errors });
200
+ return { config: null, errors, rawData };
391
201
  }
392
- async _download({
393
- repository,
394
- owner,
395
- octokit
396
- }) {
202
+ async _download({ repository, owner }) {
397
203
  if (!repository || !owner) {
398
- this._logger.warn("Repo or owner is not defined, cannot download the requested file");
204
+ this._logger.error("Repo or owner is not defined, cannot download the requested file");
399
205
  return null;
400
206
  }
401
- const pathList = getConfigPathCandidatesForEnvironment(this._environment);
207
+ let pathList;
208
+ switch (this._environment) {
209
+ case "development":
210
+ pathList = [CONFIG_DEV_FULL_PATH];
211
+ break;
212
+ case "production":
213
+ pathList = [CONFIG_PROD_FULL_PATH];
214
+ break;
215
+ default:
216
+ pathList = [CONFIG_PROD_FULL_PATH, CONFIG_DEV_FULL_PATH];
217
+ }
402
218
  for (const filePath of pathList) {
403
219
  try {
404
- this._logger.info("Attempting to fetch configuration", { owner, repository, filePath });
405
- const { data, headers } = await octokit.rest.repos.getContent({
220
+ this._logger.debug("Attempting to fetch configuration", { owner, repository, filePath });
221
+ const { data, headers } = await this._octokit.rest.repos.getContent({
406
222
  owner,
407
223
  repo: repository,
408
224
  path: filePath,
409
225
  mediaType: { format: "raw" }
410
226
  });
411
- this._logger.ok("Configuration file found", { owner, repository, filePath, rateLimitRemaining: headers?.["x-ratelimit-remaining"], data });
227
+ this._logger.debug("Configuration file found", { owner, repository, filePath, rateLimitRemaining: headers?.["x-ratelimit-remaining"], data });
412
228
  return data;
413
229
  } catch (err) {
414
230
  if (err && typeof err === "object" && "status" in err && err.status === 404) {
415
231
  this._logger.warn("No configuration file found", { owner, repository, filePath });
416
232
  } else {
417
- const status = err && typeof err === "object" && "status" in err ? Number(err.status) : null;
418
- const metadata = { err, owner, repository, filePath, ...status ? { status } : {} };
419
- if (status && status >= 500) {
420
- this._logger.error("Failed to download the requested file", metadata);
421
- } else {
422
- this._logger.warn("Failed to download the requested file", metadata);
423
- }
233
+ this._logger.error("Failed to download the requested file", { err, owner, repository, filePath });
424
234
  }
425
235
  }
426
236
  }
427
237
  return null;
428
238
  }
429
239
  _parseYaml(data) {
430
- this._logger.info("Will attempt to parse YAML data", { data });
240
+ this._logger.debug("Will attempt to parse YAML data", { data });
431
241
  try {
432
242
  if (data) {
433
243
  const parsedData = YAML.load(data);
434
- this._logger.ok("Parsed yaml data", { parsedData });
244
+ this._logger.debug("Parsed yaml data", { parsedData });
435
245
  return { yaml: parsedData ?? null, errors: null };
436
246
  }
437
247
  } catch (error) {
438
- this._logger.warn("Error parsing YAML", { error });
248
+ this._logger.error("Error parsing YAML", { error });
439
249
  return { errors: [error], yaml: null };
440
250
  }
441
- this._logger.warn("Could not parse YAML");
251
+ this._logger.debug("Could not parse YAML");
442
252
  return { yaml: null, errors: null };
443
253
  }
444
254
  mergeConfigurations(configuration1, configuration2) {
@@ -479,7 +289,7 @@ var ConfigurationHandler = class {
479
289
  return manifest;
480
290
  }
481
291
  } catch (e) {
482
- this._logger.warn("Could not find a valid manifest", { owner, repo, err: e });
292
+ this._logger.error("Could not find a valid manifest", { owner, repo, err: e });
483
293
  }
484
294
  return null;
485
295
  })();
@@ -494,7 +304,7 @@ var ConfigurationHandler = class {
494
304
  const errors = [...Value.Errors(manifestSchema, manifest)];
495
305
  if (errors.length) {
496
306
  for (const error of errors) {
497
- this._logger.warn("Manifest validation error", { error });
307
+ this._logger.error("Manifest validation error", { error });
498
308
  }
499
309
  throw new Error("Manifest is invalid.");
500
310
  }
@@ -45,7 +45,6 @@ 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;
49
48
  message: string;
50
49
  name: string;
51
50
  stack: string | undefined;
@@ -45,7 +45,6 @@ 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;
49
48
  message: string;
50
49
  name: string;
51
50
  stack: string | undefined;
package/dist/index.d.mts CHANGED
@@ -1,12 +1,12 @@
1
1
  import { EmitterWebhookEventName } from '@octokit/webhooks';
2
- import { C as Context } from './context-Ckj1HMjz.mjs';
3
- export { a as CommentHandler } from './context-Ckj1HMjz.mjs';
2
+ import { C as Context } from './context-sqbr2o6i.mjs';
3
+ export { a as CommentHandler } from './context-sqbr2o6i.mjs';
4
4
  import { TSchema, TAnySchema } from '@sinclair/typebox';
5
5
  import { LogLevel } from '@ubiquity-os/ubiquity-os-logger';
6
+ export { LlmCallOptions, callLlm } from './llm.mjs';
6
7
  import * as hono_types from 'hono/types';
7
8
  import { Hono } from 'hono';
8
9
  import { Manifest } from './manifest.mjs';
9
- export { callLlm } from './llm.mjs';
10
10
  import '@octokit/plugin-rest-endpoint-methods';
11
11
  import './octokit.mjs';
12
12
  import '@octokit/core/types';
@@ -15,7 +15,6 @@ import '@octokit/plugin-paginate-rest';
15
15
  import '@octokit/webhooks/node_modules/@octokit/request-error';
16
16
  import '@octokit/core';
17
17
  import 'openai/resources/chat/completions';
18
- import './signature.mjs';
19
18
 
20
19
  type Return = Record<string, unknown> | undefined | void;
21
20
  type HandlerReturn = Promise<Return> | Return;
package/dist/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import { EmitterWebhookEventName } from '@octokit/webhooks';
2
- import { C as Context } from './context-BE4WjJZf.js';
3
- export { a as CommentHandler } from './context-BE4WjJZf.js';
2
+ import { C as Context } from './context-BbEmsEct.js';
3
+ export { a as CommentHandler } from './context-BbEmsEct.js';
4
4
  import { TSchema, TAnySchema } from '@sinclair/typebox';
5
5
  import { LogLevel } from '@ubiquity-os/ubiquity-os-logger';
6
+ export { LlmCallOptions, callLlm } from './llm.js';
6
7
  import * as hono_types from 'hono/types';
7
8
  import { Hono } from 'hono';
8
9
  import { Manifest } from './manifest.js';
9
- export { callLlm } from './llm.js';
10
10
  import '@octokit/plugin-rest-endpoint-methods';
11
11
  import './octokit.js';
12
12
  import '@octokit/core/types';
@@ -15,7 +15,6 @@ import '@octokit/plugin-paginate-rest';
15
15
  import '@octokit/webhooks/node_modules/@octokit/request-error';
16
16
  import '@octokit/core';
17
17
  import 'openai/resources/chat/completions';
18
- import './signature.js';
19
18
 
20
19
  type Return = Record<string, unknown> | undefined | void;
21
20
  type HandlerReturn = Promise<Return> | Return;