@n1creator/openacp-cli 2026.712.12 → 2026.713.2

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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 1,
3
+ "generatedAt": "2026-07-13T00:00:00.000Z",
4
+ "pluginCount": 0,
5
+ "plugins": [],
6
+ "categories": []
7
+ }
package/dist/index.d.ts CHANGED
@@ -259,6 +259,14 @@ interface InstallContext {
259
259
  log: Logger$1;
260
260
  /** Root of the OpenACP instance directory (e.g. ~/.openacp) */
261
261
  instanceRoot?: string;
262
+ /** Atomically derive lifecycle settings from a fresh cross-process-locked snapshot. */
263
+ transactSettings?<T>(prepare: (current: Record<string, unknown>) => {
264
+ settings: Record<string, unknown>;
265
+ result: T;
266
+ } | Promise<{
267
+ settings: Record<string, unknown>;
268
+ result: T;
269
+ }>): Promise<T>;
262
270
  }
263
271
  /**
264
272
  * Context provided to the `migrate()` hook at boot time when the plugin's
@@ -800,6 +808,15 @@ interface ValidationResult {
800
808
  valid: boolean;
801
809
  errors?: string[];
802
810
  }
811
+ /** A settings snapshot and optional in-process side effect committed as one transaction. */
812
+ interface PluginSettingsMutation<T> {
813
+ settings: Record<string, unknown>;
814
+ result: T;
815
+ /** Runs only after the new settings snapshot has been persisted. */
816
+ apply?: () => void | Promise<void>;
817
+ /** Restores any partially-applied side effect when apply fails. */
818
+ rollback?: () => void | Promise<void>;
819
+ }
803
820
  /**
804
821
  * Manages per-plugin settings files.
805
822
  *
@@ -810,20 +827,34 @@ interface ValidationResult {
810
827
  */
811
828
  declare class SettingsManager {
812
829
  private basePath;
830
+ private static readonly mutationTails;
813
831
  constructor(basePath: string);
814
832
  /** Returns the base path for all plugin settings directories. */
815
833
  getBasePath(): string;
816
834
  /** Create a SettingsAPI instance scoped to a specific plugin. */
817
835
  createAPI(pluginName: string): SettingsAPI;
818
- /** Load a plugin's settings from disk. Returns empty object if file doesn't exist. */
836
+ /** Load a fresh plugin settings snapshot. Returns empty object if the file doesn't exist. */
819
837
  loadSettings(pluginName: string): Promise<Record<string, unknown>>;
820
838
  /** Validate settings against a Zod schema. Returns valid if no schema is provided. */
821
839
  validateSettings(_pluginName: string, settings: unknown, schema?: ZodSchema): ValidationResult;
822
840
  /** Resolve the absolute path to a plugin's settings.json file. */
823
841
  getSettingsPath(pluginName: string): string;
824
842
  getPluginSettings(pluginName: string): Promise<Record<string, unknown>>;
843
+ /**
844
+ * Serialize a read/prepare/persist/apply transaction for one plugin.
845
+ *
846
+ * The transaction holds both an in-process queue and a filesystem lock. Its
847
+ * prepare callback receives a fresh disk snapshot. Persistence uses a content
848
+ * revision CAS; a pre-commit conflict is retried from a new snapshot, while an
849
+ * exhausted conflict aborts without applying the runtime side effect. Apply
850
+ * failures restore the exact previous file content and invoke runtime rollback
851
+ * before releasing the cross-process lock.
852
+ */
853
+ transactPluginSettings<T>(pluginName: string, prepare: (current: Record<string, unknown>) => PluginSettingsMutation<T> | Promise<PluginSettingsMutation<T>>): Promise<T>;
825
854
  /** Merge updates into existing settings (shallow merge). */
826
855
  updatePluginSettings(pluginName: string, updates: Record<string, unknown>): Promise<void>;
856
+ private transactOnce;
857
+ private static serialize;
827
858
  }
828
859
 
829
860
  /** Log rotation and verbosity settings. */
@@ -1577,11 +1608,13 @@ interface ProxyRouteChangeResult {
1577
1608
 
1578
1609
  declare const PROXY_ENV_KEYS: readonly ["HTTP_PROXY", "HTTPS_PROXY", "ALL_PROXY", "NO_PROXY", "http_proxy", "https_proxy", "all_proxy", "no_proxy", "NODE_USE_ENV_PROXY"];
1579
1610
  type RouteTester = (fetcher: typeof fetch) => Promise<void>;
1611
+ type ConnectivityPreflight = (fetcher: typeof fetch) => Promise<void>;
1580
1612
  type RouteChangedListener = (scope: string, route: ProxyRoute) => void | Promise<void>;
1581
1613
  /** Scoped network policy. It never mutates process.env or a global fetch dispatcher. */
1582
1614
  declare class ProxyService {
1583
1615
  private readonly retiredLeaseTimeoutMs;
1584
1616
  private readonly allowedNodeEnvironmentFlags;
1617
+ private readonly connectivityPreflight;
1585
1618
  private readonly store;
1586
1619
  private readonly scopes;
1587
1620
  private readonly testers;
@@ -1591,7 +1624,7 @@ declare class ProxyService {
1591
1624
  private mutationQueue;
1592
1625
  private policyGeneration;
1593
1626
  private readonly maxTransports;
1594
- constructor(instanceRoot: string, retiredLeaseTimeoutMs?: number, allowedNodeEnvironmentFlags?: ReadonlySet<string>);
1627
+ constructor(instanceRoot: string, retiredLeaseTimeoutMs?: number, allowedNodeEnvironmentFlags?: ReadonlySet<string>, connectivityPreflight?: ConnectivityPreflight);
1595
1628
  private serialize;
1596
1629
  getPolicyGeneration(): number;
1597
1630
  private invalidatePolicyBeforeCommit;
@@ -1654,6 +1687,7 @@ declare class ProxyService {
1654
1687
  status(): ProxyStatus;
1655
1688
  private validateRoute;
1656
1689
  private testCandidateRoutes;
1690
+ private candidateTransportIdentity;
1657
1691
  private createProfileFetch;
1658
1692
  /** Direct transport that ignores daemon-wide env proxy flags without global mutation. */
1659
1693
  private createDirectFetch;
@@ -1861,6 +1895,11 @@ type ProviderFactory = (config: SpeechServiceConfig) => {
1861
1895
  stt: Map<string, STTProvider>;
1862
1896
  tts: Map<string, TTSProvider>;
1863
1897
  };
1898
+ /** A fully-built provider replacement that can be committed without construction work. */
1899
+ interface PreparedProviderRefresh {
1900
+ commit(): void;
1901
+ rollback(): void;
1902
+ }
1864
1903
  /**
1865
1904
  * Central service for speech-to-text and text-to-speech operations.
1866
1905
  *
@@ -1875,6 +1914,9 @@ declare class SpeechService {
1875
1914
  private sttProviders;
1876
1915
  private ttsProviders;
1877
1916
  private providerFactory?;
1917
+ private factoryOwnedSTT;
1918
+ private factoryOwnedTTS;
1919
+ private runtimeRevision;
1878
1920
  constructor(config: SpeechServiceConfig);
1879
1921
  /** Set a factory function that can recreate providers from config (for hot-reload) */
1880
1922
  setProviderFactory(factory: ProviderFactory): void;
@@ -1907,6 +1949,14 @@ declare class SpeechService {
1907
1949
  synthesize(text: string, options?: TTSOptions): Promise<TTSResult>;
1908
1950
  /** Replace the active config without rebuilding providers. Use `refreshProviders` to also rebuild. */
1909
1951
  updateConfig(config: SpeechServiceConfig): void;
1952
+ /**
1953
+ * Build and validate a complete factory-owned provider replacement without
1954
+ * changing the active runtime. The returned commit is revision-checked and
1955
+ * preserves providers registered by external plugins. Rollback restores the
1956
+ * exact config, maps, ownership sets, and provider object references captured
1957
+ * immediately before commit.
1958
+ */
1959
+ prepareProviderRefresh(newConfig: SpeechServiceConfig): PreparedProviderRefresh;
1910
1960
  /**
1911
1961
  * Reloads TTS and STT providers from a new config snapshot.
1912
1962
  *
@@ -1917,6 +1967,11 @@ declare class SpeechService {
1917
1967
  refreshProviders(newConfig: SpeechServiceConfig): void;
1918
1968
  }
1919
1969
 
1970
+ interface GroqAccessCheck {
1971
+ ok: boolean;
1972
+ status?: number;
1973
+ message: string;
1974
+ }
1920
1975
  /**
1921
1976
  * Speech-to-text provider backed by Groq's hosted Whisper API.
1922
1977
  *
@@ -1931,8 +1986,12 @@ declare class GroqSTT implements STTProvider {
1931
1986
  private defaultModel;
1932
1987
  private scopedFetch;
1933
1988
  private getScopedFetch?;
1989
+ private endpoint;
1990
+ private accessEndpoint;
1934
1991
  readonly name = "groq";
1935
- constructor(apiKey: string, defaultModel?: string, scopedFetch?: typeof fetch, getScopedFetch?: (() => typeof fetch) | undefined);
1992
+ constructor(apiKey: string, defaultModel?: string, scopedFetch?: typeof fetch, getScopedFetch?: (() => typeof fetch) | undefined, endpoint?: string, accessEndpoint?: string);
1993
+ /** Validate credentials without sending audio or exposing a provider response body. */
1994
+ checkAccess(signal?: AbortSignal): Promise<GroqAccessCheck>;
1936
1995
  /**
1937
1996
  * Transcribes audio using the Groq Whisper API.
1938
1997
  *
@@ -3291,6 +3350,7 @@ type RegisterInput = Omit<PluginEntry, 'installedAt' | 'updatedAt'>;
3291
3350
  declare class PluginRegistry {
3292
3351
  private registryPath;
3293
3352
  private data;
3353
+ private pending;
3294
3354
  constructor(registryPath: string);
3295
3355
  /** Return all installed plugins as a Map. */
3296
3356
  list(): Map<string, PluginEntry>;
@@ -3298,6 +3358,8 @@ declare class PluginRegistry {
3298
3358
  get(name: string): PluginEntry | undefined;
3299
3359
  /** Record a newly installed plugin. Timestamps are set automatically. */
3300
3360
  register(name: string, entry: RegisterInput): void;
3361
+ /** Restore an exact pre-transaction entry, including its original timestamps. */
3362
+ restore(name: string, entry: PluginEntry | undefined): void;
3301
3363
  /** Remove a plugin from the registry. */
3302
3364
  remove(name: string): void;
3303
3365
  /** Enable or disable a plugin. Disabled plugins are skipped at boot. */
@@ -3310,8 +3372,15 @@ declare class PluginRegistry {
3310
3372
  listBySource(source: PluginEntry['source']): Map<string, PluginEntry>;
3311
3373
  /** Load registry data from disk. Silently starts empty if file doesn't exist. */
3312
3374
  load(): Promise<void>;
3375
+ /** Read an independent disk snapshot without changing in-memory data or pending writes. */
3376
+ readSnapshot(): Promise<Map<string, PluginEntry>>;
3377
+ private loadDisk;
3378
+ private replayPending;
3313
3379
  /** Persist registry data to disk. */
3314
3380
  save(): Promise<void>;
3381
+ /** Exact bytes that save() will persist for the current replayed state. */
3382
+ serializeCurrent(): Buffer;
3383
+ private saveUnlocked;
3315
3384
  }
3316
3385
 
3317
3386
  /** Options for constructing a LifecycleManager. All fields are optional with sensible defaults. */
@@ -3362,6 +3431,8 @@ declare class LifecycleManager {
3362
3431
  settingsManager: SettingsManager | undefined;
3363
3432
  private pluginRegistry;
3364
3433
  private _instanceRoot;
3434
+ private installRecoveryChecked;
3435
+ private communityRecoveryError;
3365
3436
  private contexts;
3366
3437
  private loadOrder;
3367
3438
  private _loaded;
@@ -4134,6 +4205,7 @@ interface CreateCodeOpts {
4134
4205
  codeTtlMs?: number;
4135
4206
  }
4136
4207
 
4208
+ type TokenStoreWriter = (filePath: string, data: string, encoding: BufferEncoding) => Promise<void>;
4137
4209
  /**
4138
4210
  * Persists JWT tokens and one-time authorization codes to a JSON file.
4139
4211
  *
@@ -4147,19 +4219,31 @@ interface CreateCodeOpts {
4147
4219
  */
4148
4220
  declare class TokenStore {
4149
4221
  private filePath;
4222
+ private readonly writer;
4150
4223
  private tokens;
4151
4224
  private codes;
4152
4225
  private savePromise;
4153
4226
  private savePending;
4154
- constructor(filePath: string);
4227
+ private saveError;
4228
+ private closePromise;
4229
+ private state;
4230
+ constructor(filePath: string, writer?: TokenStoreWriter);
4231
+ private assertOpen;
4155
4232
  /** Loads token and code state from disk. Safe to call at startup; missing file is not an error. */
4156
4233
  load(): Promise<void>;
4234
+ /** Requests a persistence pass and waits until the coalesced queue is durable. */
4157
4235
  save(): Promise<void>;
4236
+ private writeSnapshot;
4158
4237
  /**
4159
4238
  * Coalesces concurrent writes: if a save is in-flight, sets a pending flag
4160
4239
  * so the next save fires immediately after the current one completes.
4161
4240
  */
4162
4241
  private scheduleSave;
4242
+ /**
4243
+ * Internal queue entry point. It is also used by close() to persist mutations
4244
+ * that were accepted while the store was open, such as a debounced lastUsedAt.
4245
+ */
4246
+ private enqueueSave;
4163
4247
  /** Creates a new token record and schedules a persist. Returns the stored token including its generated id. */
4164
4248
  create(opts: CreateTokenOpts): StoredToken;
4165
4249
  get(id: string): StoredToken | undefined;
@@ -4175,8 +4259,17 @@ declare class TokenStore {
4175
4259
  * so flushing on every call would cause excessive disk I/O.
4176
4260
  */
4177
4261
  updateLastUsed(id: string): void;
4178
- /** Wait for any in-flight and pending saves to complete */
4262
+ private drainSaveQueue;
4263
+ /** Wait for all accepted mutations to become durable. */
4179
4264
  flush(): Promise<void>;
4265
+ /**
4266
+ * Stops delayed work and drains every save already owned by this store.
4267
+ *
4268
+ * Callers must first stop request producers, then await close() before removing
4269
+ * the store directory. The promise is idempotent so both the HTTP server close
4270
+ * hook and its owning plugin teardown can enforce the same lifecycle boundary.
4271
+ */
4272
+ close(): Promise<void>;
4180
4273
  destroy(): void;
4181
4274
  /** Associate a user ID with a token. Called by identity plugin after /identity/setup. */
4182
4275
  setUserId(tokenId: string, userId: string): void;