@alfe.ai/integrations 0.0.27 → 0.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -245,6 +245,8 @@ interface ConfigSchemaField {
245
245
  select_options?: SelectOption[];
246
246
  /** OAuth provider identifier for oauth_connect fields */
247
247
  oauth_provider?: string;
248
+ /** If true, this field is not shown in the dashboard UI (install wizard or configure modal) */
249
+ hidden?: boolean;
248
250
  /** Only show this field if another field has a truthy value (string) or matches a specific value (object) */
249
251
  depends_on_field?: string | {
250
252
  key: string;
@@ -379,6 +381,8 @@ interface IntegrationStateEntry {
379
381
  installedAt: string;
380
382
  config: Record<string, unknown>;
381
383
  error?: string;
384
+ /** Number of consecutive auto-reinstall attempts. Reset on success or explicit reinstall. */
385
+ reinstallAttempts?: number;
382
386
  }
383
387
  interface IntegrationsStateFile {
384
388
  version: number;
@@ -569,6 +573,18 @@ declare class IntegrationManager {
569
573
  * Returns false if the state says installed but files are missing (corrupted install).
570
574
  */
571
575
  isInstallIntact(integrationId: string): boolean;
576
+ /**
577
+ * Get the number of consecutive auto-reinstall attempts for an integration.
578
+ */
579
+ getReinstallAttempts(integrationId: string): number;
580
+ /**
581
+ * Increment the auto-reinstall attempt counter.
582
+ */
583
+ incrementReinstallAttempts(integrationId: string): void;
584
+ /**
585
+ * Reset the auto-reinstall attempt counter.
586
+ */
587
+ resetReinstallAttempts(integrationId: string): void;
572
588
  /**
573
589
  * Get a specific integration by name.
574
590
  */
@@ -639,6 +655,14 @@ declare class StateManager {
639
655
  * Check if an integration is in a given status.
640
656
  */
641
657
  hasStatus(name: string, ...statuses: IntegrationStatus[]): boolean;
658
+ /**
659
+ * Increment the auto-reinstall attempt counter.
660
+ */
661
+ incrementReinstallAttempts(name: string): void;
662
+ /**
663
+ * Reset the auto-reinstall attempt counter (on success or explicit reinstall).
664
+ */
665
+ resetReinstallAttempts(name: string): void;
642
666
  }
643
667
  //#endregion
644
668
  //#region src/hooks.d.ts
@@ -867,6 +891,12 @@ interface IIntegrationManager {
867
891
  }>;
868
892
  /** Check if an integration's install directory and manifest are intact on disk */
869
893
  isInstallIntact(integrationId: string): Promise<boolean>;
894
+ /** Get the number of consecutive auto-reinstall attempts */
895
+ getReinstallAttempts(integrationId: string): number;
896
+ /** Increment the auto-reinstall attempt counter */
897
+ incrementReinstallAttempts(integrationId: string): void;
898
+ /** Reset the auto-reinstall attempt counter */
899
+ resetReinstallAttempts(integrationId: string): void;
870
900
  }
871
901
  declare class IntegrationManagerAdapter implements IIntegrationManager {
872
902
  private readonly manager;
@@ -887,6 +917,9 @@ declare class IntegrationManagerAdapter implements IIntegrationManager {
887
917
  configApplied: boolean;
888
918
  }>;
889
919
  isInstallIntact(integrationId: string): Promise<boolean>;
920
+ getReinstallAttempts(integrationId: string): number;
921
+ incrementReinstallAttempts(integrationId: string): void;
922
+ resetReinstallAttempts(integrationId: string): void;
890
923
  }
891
924
  //#endregion
892
925
  export { type HookEnvOptions, type HookResult, type IIntegrationManager, type InstalledInfo, Installer, InstallerError, type IntegrationConfigureParams, type IntegrationHealthParams, type IntegrationInfo, type IntegrationInstallParams, IntegrationManager, IntegrationManagerAdapter, type IntegrationManagerOptions, type IntegrationRemoveParams, LockManager, OpenClawApplier, type OpenClawApplierOptions, Registry, type RegistryEntry, type RegistryFetcher, type RegistryIndex, RegistryResolveError, type ResolvedIntegration, Resolver, type RuntimeApplier, type RuntimeDesiredState, type RuntimeLockFile, type RuntimePluginEntry, type RuntimeSkillEntry, StateManager, buildHookEnv, resolveInstallsForRuntime, runHook, runHookWithContext };
package/dist/index.js CHANGED
@@ -470,6 +470,24 @@ var StateManager = class {
470
470
  if (!entry) return false;
471
471
  return statuses.includes(entry.status);
472
472
  }
473
+ /**
474
+ * Increment the auto-reinstall attempt counter.
475
+ */
476
+ incrementReinstallAttempts(name) {
477
+ const state = this.read();
478
+ if (!(name in state.integrations)) return;
479
+ state.integrations[name].reinstallAttempts = (state.integrations[name].reinstallAttempts ?? 0) + 1;
480
+ this.write(state);
481
+ }
482
+ /**
483
+ * Reset the auto-reinstall attempt counter (on success or explicit reinstall).
484
+ */
485
+ resetReinstallAttempts(name) {
486
+ const state = this.read();
487
+ if (!(name in state.integrations)) return;
488
+ state.integrations[name].reinstallAttempts = 0;
489
+ this.write(state);
490
+ }
473
491
  };
474
492
  //#endregion
475
493
  //#region src/lock.ts
@@ -1041,10 +1059,19 @@ var IntegrationManager = class {
1041
1059
  continue;
1042
1060
  }
1043
1061
  const { plugins, skills, config: runtimeConfig } = resolveInstallsForRuntime(manifest, runtimeName);
1062
+ const pluginFailures = [];
1044
1063
  for (const plugin of plugins) {
1045
1064
  this.log.info(`Applying plugin ${plugin.package} to ${runtimeName}`);
1046
- await applier.applyPlugin(plugin.package, installPath, { force: opts?.forcePlugins });
1065
+ try {
1066
+ await applier.applyPlugin(plugin.package, installPath, { force: opts?.forcePlugins });
1067
+ } catch (err) {
1068
+ const msg = err instanceof Error ? err.message : String(err);
1069
+ this.log.error(`Failed to apply plugin ${plugin.package}: ${msg}`);
1070
+ pluginFailures.push(plugin.package);
1071
+ }
1047
1072
  }
1073
+ if (pluginFailures.length > 0 && pluginFailures.length === plugins.length) throw new Error(`All plugins failed to install: ${pluginFailures.join(", ")}`);
1074
+ if (pluginFailures.length > 0) this.log.warn(`Continuing activation with ${String(pluginFailures.length)} failed plugin(s): ${pluginFailures.join(", ")}`);
1048
1075
  for (const skill of skills) if (skill.clawhub) {
1049
1076
  this.log.info(`Installing ClawHub skill ${skill.clawhub} to ${runtimeName}`);
1050
1077
  await applier.applyClawHubSkill(skill.clawhub);
@@ -1074,7 +1101,8 @@ var IntegrationManager = class {
1074
1101
  configApplied = true;
1075
1102
  }
1076
1103
  }
1077
- if (plugins.length > 0 || skills.length > 0) this.lockManager.addEntries(runtimeName, integrationId, manifest.version, plugins, skills, installPath);
1104
+ const appliedPlugins = plugins.filter((p) => !pluginFailures.includes(p.package));
1105
+ if (appliedPlugins.length > 0 || skills.length > 0) this.lockManager.addEntries(runtimeName, integrationId, manifest.version, appliedPlugins, skills, installPath);
1078
1106
  }
1079
1107
  this.state.setStatus(integrationId, "active");
1080
1108
  if (manifest.hooks.post_activate) {
@@ -1336,6 +1364,24 @@ var IntegrationManager = class {
1336
1364
  return existsSync(join(this.installer.getInstallPath(integrationId), "alfe-integration.yaml"));
1337
1365
  }
1338
1366
  /**
1367
+ * Get the number of consecutive auto-reinstall attempts for an integration.
1368
+ */
1369
+ getReinstallAttempts(integrationId) {
1370
+ return this.state.get(integrationId)?.reinstallAttempts ?? 0;
1371
+ }
1372
+ /**
1373
+ * Increment the auto-reinstall attempt counter.
1374
+ */
1375
+ incrementReinstallAttempts(integrationId) {
1376
+ this.state.incrementReinstallAttempts(integrationId);
1377
+ }
1378
+ /**
1379
+ * Reset the auto-reinstall attempt counter.
1380
+ */
1381
+ resetReinstallAttempts(integrationId) {
1382
+ this.state.resetReinstallAttempts(integrationId);
1383
+ }
1384
+ /**
1339
1385
  * Get a specific integration by name.
1340
1386
  */
1341
1387
  get(name) {
@@ -1829,6 +1875,15 @@ var IntegrationManagerAdapter = class {
1829
1875
  isInstallIntact(integrationId) {
1830
1876
  return Promise.resolve(this.manager.isInstallIntact(integrationId));
1831
1877
  }
1878
+ getReinstallAttempts(integrationId) {
1879
+ return this.manager.getReinstallAttempts(integrationId);
1880
+ }
1881
+ incrementReinstallAttempts(integrationId) {
1882
+ this.manager.incrementReinstallAttempts(integrationId);
1883
+ }
1884
+ resetReinstallAttempts(integrationId) {
1885
+ this.manager.resetReinstallAttempts(integrationId);
1886
+ }
1832
1887
  };
1833
1888
  //#endregion
1834
1889
  export { Installer, InstallerError, IntegrationManager, IntegrationManagerAdapter, LockManager, OpenClawApplier, Registry, RegistryResolveError, Resolver, StateManager, buildHookEnv, resolveInstallsForRuntime, runHook, runHookWithContext };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfe.ai/integrations",
3
- "version": "0.0.27",
3
+ "version": "0.0.28",
4
4
  "description": "Integration lifecycle management for Alfe — registry, resolution, installation, and state",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -13,7 +13,7 @@
13
13
  },
14
14
  "dependencies": {
15
15
  "@auriclabs/logger": "^0.1.1",
16
- "@alfe.ai/integration-manifest": "^0.0.9"
16
+ "@alfe.ai/integration-manifest": "^0.0.10"
17
17
  },
18
18
  "files": [
19
19
  "dist"