import type { Envelope, Inspector, InspectorQuery, LinkedBundle, RuntimeActor, WorkerQuery } from '@devvit/protos';
import { Definition, InspectorDescriptions, InspectorUpdate } from '@devvit/protos';
import { Empty } from '@devvit/protos/types/google/protobuf/empty.js';
import type { Disposable } from '@devvit/shared-types/Disposable.js';
import type { Observable } from 'rxjs';
import type { WorkerPathResolver } from '../../lib/WorkerPathResolver.js';
import type { SystemWorkerSpec } from '../../workers/SystemWorkerSpec.js';
import type { EnvelopeRecipient } from '../envelope/EnvelopeRecipient.js';
import { CentralDispatcher } from '../envelope/dispatcher/CentralDispatcher.js';
import type { EnvelopeDispatcher } from '../envelope/dispatcher/EnvelopeDispatcher.js';
import type { ActorRef } from './ActorRef.js';
import type { GCPolicy, GCPolicyFactory } from './GCPolicy.js';
export type WorkerErrorLogger = typeof console.error;
/**
 * Spec for what runtimes should do.
 */
export type CommonRuntimeLike = Disposable & {
    start(): Promise<void>;
    load(bundle: LinkedBundle): Promise<void>;
    loadAndGetActorRef(bundle: LinkedBundle): Promise<ActorRef>;
    forceUnload(hostname: string): Promise<void>;
    getActorRef(hostname: string): ActorRef;
    getInspector(): Inspector | undefined;
    /**
     * plugins are native actors.  They implicitly have hostnames, but aren't unloadable.
     */
    getPlugin<T>(def: Definition): T;
    provide<T>(def: Definition, service: T): void;
};
export declare abstract class CommonRuntime implements CommonRuntimeLike, WorkerPathResolver, RuntimeActor, Inspector, EnvelopeDispatcher {
    #private;
    get hostname(): string;
    /** Get the dispatcher, only meant to be used in a debug mode REPL */
    get debugDispatcher(): CentralDispatcher | undefined;
    readonly namespace: string;
    readonly refCounts: {
        [hostname: string]: number;
    };
    readonly policy: GCPolicy;
    constructor(namespace: string, policyFactory?: GCPolicyFactory, workerErrorLogger?: WorkerErrorLogger, systemWorkerSpecs?: SystemWorkerSpec[]);
    /**
     * Bind a recipient to the dispatcher. Allow a recipient to send and receive
     * envelopes but not to be used (dependend on).
     */
    bind(recipient: EnvelopeRecipient): void;
    release(recipient: Readonly<EnvelopeRecipient>): Promise<void>;
    unbind(recipient: Readonly<EnvelopeRecipient>): void;
    post(caller: Readonly<EnvelopeRecipient>, envelope: Envelope): void;
    onBind(dispatcher: Readonly<EnvelopeDispatcher>): void;
    onUnbind(dispatcher: Readonly<EnvelopeDispatcher>): void;
    /**
     * Return the path to the worker.bootstrap.cjs file
     */
    getBootstrapPath(): string;
    /**
     * Return the path to the worker.{name}.cjs file
     */
    abstract pathForName(name: string): string;
    /**
     * Called after the Supervisor is available
     */
    protected abstract loadPlugins(dispatcher: CentralDispatcher): Promise<void>;
    /**
     * Starts the  Supervisor and loads Plugins
     */
    start(): Promise<void>;
    /**
     * Teardown the Runtime, terminating all Workers and connections
     */
    dispose(): Promise<void>;
    /**
     * Load an app and all dependencies from the given bundle
     */
    load(bundle: LinkedBundle): Promise<void>;
    loadAndGetActorRef(bundle: LinkedBundle): Promise<ActorRef>;
    forceUnload(hostname: string): Promise<void>;
    /**
     * Get an ActorRef by hostname.
     */
    getActorRef(hostname: string): ActorRef;
    /**
     * Returns an RPC connection to a plugin
     */
    getPlugin<T>(def: Definition): T;
    /**
     * Returns the inspector, if available. to-do: how do we get callers to unbind
     * clients when they're done with them?
     */
    getInspector(): Inspector;
    /**
     * Add a Definition instance as an addressable and usable service.
     */
    provide<T>(definition: Definition, service: T): void;
    /**
     * Returns true if there is an active connection to the hostname.
     */
    isBound(recipient: Readonly<EnvelopeRecipient>): boolean;
    /**
     * Create a client to the server at hostname. The server is assumed to exist.
     * Each client has a unique hostname that doesn't collide even when there are
     * multiple clients to the same server. The client hostname is under the
     * namespace of the runtime and has no resemblance to the server. Eg, the
     * server may answer to logger.plugins.local and the client may call as
     * 123.local.
     *
     * A client should be unbound when no longer used. to-do: reference count
     * with a FinalizationRegistry or a WeakMap.
     */
    getClient<T>(serverHostname: string, definition: Definition): T & EnvelopeRecipient;
    NewWorker(bundle: LinkedBundle): Promise<Empty>;
    TerminateWorker(query: WorkerQuery): Promise<Empty>;
    ListActors(request: InspectorQuery): Promise<InspectorDescriptions>;
    ActorChanges(_request: Empty): Observable<InspectorUpdate>;
}
//# sourceMappingURL=CommonRuntime.d.ts.map