@kici-dev/orchestrator 0.1.12 → 0.1.13

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.
Files changed (33) hide show
  1. package/dist/cli/commands/agent-service/install.d.ts +7 -0
  2. package/dist/cli/commands/agent-service/logs.d.ts +8 -3
  3. package/dist/cli/commands/agent-service/restart.d.ts +5 -1
  4. package/dist/cli/commands/agent-service/start.d.ts +5 -1
  5. package/dist/cli/commands/agent-service/status.d.ts +5 -1
  6. package/dist/cli/commands/agent-service/stop.d.ts +5 -1
  7. package/dist/cli/commands/agent-service/uninstall.d.ts +6 -2
  8. package/dist/cli/commands/agent-service/upgrade.d.ts +13 -3
  9. package/dist/cli/commands/orchestrator-service/logs.d.ts +4 -0
  10. package/dist/cli/commands/orchestrator-service/restart.d.ts +5 -1
  11. package/dist/cli/commands/orchestrator-service/start.d.ts +5 -1
  12. package/dist/cli/commands/orchestrator-service/status.d.ts +4 -0
  13. package/dist/cli/commands/orchestrator-service/stop.d.ts +5 -1
  14. package/dist/cli/commands/orchestrator-service/uninstall.d.ts +6 -2
  15. package/dist/cli/commands/orchestrator-service/upgrade.d.ts +9 -0
  16. package/dist/cli/commands/shared/versioned-upgrade.d.ts +54 -2
  17. package/dist/cli/service/compose.d.ts +3 -2
  18. package/dist/cli/service/index.d.ts +7 -1
  19. package/dist/cli/service/instance/index-file.d.ts +30 -0
  20. package/dist/cli/service/instance/manifest.d.ts +21 -0
  21. package/dist/cli/service/instance/resolve.d.ts +59 -0
  22. package/dist/cli/service/instance/types.d.ts +55 -0
  23. package/dist/cli/service/launchd.d.ts +19 -1
  24. package/dist/cli/service/platform-detect.d.ts +29 -9
  25. package/dist/cli/service/systemd.d.ts +2 -1
  26. package/dist/cli/service/types.d.ts +28 -0
  27. package/dist/cli/service/windows.d.ts +2 -1
  28. package/dist/cli.js +1670 -1029
  29. package/dist/metrics/prometheus.d.ts +32 -4
  30. package/dist/server.js +19 -19
  31. package/dist/standalone.js +19 -19
  32. package/package.json +4 -4
  33. package/sbom.spdx.json +36 -36
@@ -3,6 +3,13 @@
3
3
  *
4
4
  * Registers the agent as a native system service on the current platform.
5
5
  * Accepts orchestrator URL and token for connecting to the orchestrator.
6
+ *
7
+ * Targeting is folder-anchored: the install writes an instance manifest
8
+ * into the deploy folder (`--instance-dir`, default: CWD) and appends a
9
+ * row to the host-wide instance index so every lifecycle command can
10
+ * reconstruct the ServiceConfig without re-deriving paths. A create-path
11
+ * guard refuses to clobber a same-named foreign instance unless `--force`
12
+ * is passed.
6
13
  */
7
14
  import type { Command } from 'commander';
8
15
  export declare function registerAgentInstall(agent: Command): void;
@@ -1,8 +1,13 @@
1
1
  /**
2
- * `kici-admin agent-service logs` command.
2
+ * `kici-admin agent logs` command.
3
3
  *
4
- * Tails and follows agent service logs with filtering.
5
- * Delegates to the platform-specific service manager.
4
+ * Tails and follows agent service logs with filtering by time, level,
5
+ * and output format. Delegates to the platform-specific service
6
+ * manager's logs() method.
7
+ *
8
+ * Target resolution goes through resolveInstance — the same priority chain
9
+ * every lifecycle command uses (--instance-dir > --name > CWD manifest >
10
+ * refusal with candidate list).
6
11
  */
7
12
  import type { Command } from 'commander';
8
13
  export declare function registerAgentLogsCommand(parent: Command): void;
@@ -1,7 +1,11 @@
1
1
  /**
2
2
  * `kici-admin agent restart` command.
3
3
  *
4
- * Restarts the agent service.
4
+ * Restarts the agent service. Target resolution goes through
5
+ * resolveInstance — the same priority chain every lifecycle command uses
6
+ * (--instance-dir > --name > CWD manifest > refusal with candidate list).
7
+ * `--name` has no default; every invocation must resolve via one of the
8
+ * above paths.
5
9
  */
6
10
  import type { Command } from 'commander';
7
11
  export declare function registerAgentRestart(agent: Command): void;
@@ -1,7 +1,11 @@
1
1
  /**
2
2
  * `kici-admin agent start` command.
3
3
  *
4
- * Starts the agent service.
4
+ * Starts the agent service. Target resolution goes through
5
+ * resolveInstance — the same priority chain every lifecycle command uses
6
+ * (--instance-dir > --name > CWD manifest > refusal with candidate list).
7
+ * `--name` has no default; every invocation must resolve via one of the
8
+ * above paths.
5
9
  */
6
10
  import type { Command } from 'commander';
7
11
  export declare function registerAgentStart(agent: Command): void;
@@ -1,9 +1,13 @@
1
1
  /**
2
- * `kici-admin agent-service status` command.
2
+ * `kici-admin agent status` command.
3
3
  *
4
4
  * Shows OS-level service status (state, PID, uptime) and queries
5
5
  * the running agent's health API for agent-specific info (labels,
6
6
  * orchestrator connection, current job).
7
+ *
8
+ * Target resolution goes through resolveInstance — the same priority chain
9
+ * every lifecycle command uses (--instance-dir > --name > CWD manifest >
10
+ * refusal with candidate list).
7
11
  */
8
12
  import type { Command } from 'commander';
9
13
  export declare function registerAgentStatusCommand(parent: Command): void;
@@ -1,7 +1,11 @@
1
1
  /**
2
2
  * `kici-admin agent stop` command.
3
3
  *
4
- * Stops the agent service.
4
+ * Stops the agent service. Target resolution goes through
5
+ * resolveInstance — the same priority chain every lifecycle command uses
6
+ * (--instance-dir > --name > CWD manifest > refusal with candidate list).
7
+ * `--name` has no default; every invocation must resolve via one of the
8
+ * above paths.
5
9
  */
6
10
  import type { Command } from 'commander';
7
11
  export declare function registerAgentStop(agent: Command): void;
@@ -1,8 +1,12 @@
1
1
  /**
2
2
  * `kici-admin agent uninstall` command.
3
3
  *
4
- * Removes the agent service registration.
5
- * Preserves config files and logs per user decision.
4
+ * Removes the agent service registration. Target resolution goes
5
+ * through resolveInstance the same priority chain every lifecycle command
6
+ * uses (--instance-dir > --name > CWD manifest > refusal with candidate list).
7
+ * The manifest stays on disk so subsequent commands can still reference the
8
+ * deploy folder; the host-wide index entry is dropped unconditionally so a
9
+ * stale row never lingers after the unit is gone.
6
10
  */
7
11
  import type { Command } from 'commander';
8
12
  export declare function registerAgentUninstall(agent: Command): void;
@@ -1,10 +1,20 @@
1
1
  /**
2
- * `kici-admin agent-service upgrade` command.
2
+ * `kici-admin agent upgrade` command.
3
3
  *
4
4
  * Upgrades the agent using the versioned directory layout:
5
- * - Same pattern as orchestrator: versioned directories with symlink switching
6
- * - Extracts to agent-{version}/, symlink at agent/
5
+ * - Extracts new version alongside old versions
6
+ * - Updates symlink (Unix) or service registration (Windows) atomically
7
+ * - Preserves old versions for rollback
7
8
  * - No database migrations (agents are stateless)
9
+ *
10
+ * Targeting is folder-anchored: the resolution priority is
11
+ * 1. `--instance-dir <path>`
12
+ * 2. `--name <name>`
13
+ * 3. CWD manifest (`./.kici-agent.json`)
14
+ * 4. otherwise refuses with a candidate-list error.
15
+ *
16
+ * `--name` no longer has a default — every invocation must resolve via one
17
+ * of the above paths.
8
18
  */
9
19
  import type { Command } from 'commander';
10
20
  export declare function registerAgentUpgradeCommand(parent: Command): void;
@@ -4,6 +4,10 @@
4
4
  * Tails and follows service logs with filtering by time, level,
5
5
  * and output format. Delegates to the platform-specific service
6
6
  * manager's logs() method.
7
+ *
8
+ * Target resolution goes through resolveInstance — the same priority chain
9
+ * every lifecycle command uses (--instance-dir > --name > CWD manifest >
10
+ * refusal with candidate list).
7
11
  */
8
12
  import type { Command } from 'commander';
9
13
  export declare function registerLogsCommand(parent: Command): void;
@@ -1,7 +1,11 @@
1
1
  /**
2
2
  * `kici-admin orchestrator restart` command.
3
3
  *
4
- * Restarts the orchestrator service.
4
+ * Restarts the orchestrator service. Target resolution goes through
5
+ * resolveInstance — the same priority chain every lifecycle command uses
6
+ * (--instance-dir > --name > CWD manifest > refusal with candidate list).
7
+ * `--name` has no default; every invocation must resolve via one of the
8
+ * above paths.
5
9
  */
6
10
  import type { Command } from 'commander';
7
11
  export declare function registerOrchestratorRestart(orchestrator: Command): void;
@@ -1,7 +1,11 @@
1
1
  /**
2
2
  * `kici-admin orchestrator start` command.
3
3
  *
4
- * Starts the orchestrator service.
4
+ * Starts the orchestrator service. Target resolution goes through
5
+ * resolveInstance — the same priority chain every lifecycle command uses
6
+ * (--instance-dir > --name > CWD manifest > refusal with candidate list).
7
+ * `--name` has no default; every invocation must resolve via one of the
8
+ * above paths.
5
9
  */
6
10
  import type { Command } from 'commander';
7
11
  export declare function registerOrchestratorStart(orchestrator: Command): void;
@@ -4,6 +4,10 @@
4
4
  * Shows OS-level service status (state, PID, uptime) and queries
5
5
  * the running orchestrator's health API for KiCI-specific info
6
6
  * (mode, DB connectivity, agents, jobs, scaler).
7
+ *
8
+ * Target resolution goes through resolveInstance — the same priority chain
9
+ * every lifecycle command uses (--instance-dir > --name > CWD manifest >
10
+ * refusal with candidate list).
7
11
  */
8
12
  import type { Command } from 'commander';
9
13
  export declare function registerStatusCommand(parent: Command): void;
@@ -1,7 +1,11 @@
1
1
  /**
2
2
  * `kici-admin orchestrator stop` command.
3
3
  *
4
- * Stops the orchestrator service.
4
+ * Stops the orchestrator service. Target resolution goes through
5
+ * resolveInstance — the same priority chain every lifecycle command uses
6
+ * (--instance-dir > --name > CWD manifest > refusal with candidate list).
7
+ * `--name` has no default; every invocation must resolve via one of the
8
+ * above paths.
5
9
  */
6
10
  import type { Command } from 'commander';
7
11
  export declare function registerOrchestratorStop(orchestrator: Command): void;
@@ -1,8 +1,12 @@
1
1
  /**
2
2
  * `kici-admin orchestrator uninstall` command.
3
3
  *
4
- * Removes the orchestrator service registration.
5
- * Preserves config files, database, and logs per user decision.
4
+ * Removes the orchestrator service registration. Target resolution goes
5
+ * through resolveInstance the same priority chain every lifecycle command
6
+ * uses (--instance-dir > --name > CWD manifest > refusal with candidate list).
7
+ * The manifest stays on disk so subsequent commands can still reference the
8
+ * deploy folder; the host-wide index entry is dropped unconditionally so a
9
+ * stale row never lingers after the unit is gone.
6
10
  */
7
11
  import type { Command } from 'commander';
8
12
  export declare function registerOrchestratorUninstall(orchestrator: Command): void;
@@ -6,6 +6,15 @@
6
6
  * - Updates symlink (Unix) or service registration (Windows) atomically
7
7
  * - Preserves old versions for rollback
8
8
  * - Supports --cleanup and --rollback flags
9
+ *
10
+ * Targeting is folder-anchored: the resolution priority is
11
+ * 1. `--instance-dir <path>`
12
+ * 2. `--name <name>`
13
+ * 3. CWD manifest (`./.kici-orchestrator.json`)
14
+ * 4. otherwise refuses with a candidate-list error.
15
+ *
16
+ * `--name` no longer has a default — every invocation must resolve via one
17
+ * of the above paths.
9
18
  */
10
19
  import type { Command } from 'commander';
11
20
  export declare function registerUpgradeCommand(parent: Command): void;
@@ -7,13 +7,20 @@
7
7
  * - Preserve old versions for rollback
8
8
  * - Optional cleanup of old versions
9
9
  */
10
- import { type ServicePlatform } from '../../service/index.js';
10
+ import { type ResolvedInstance, type ServiceManager, type ServicePlatform } from '../../service/index.js';
11
+ import type { ServiceConfig } from '../../service/types.js';
11
12
  /** Component types that can be upgraded. */
12
13
  type UpgradeComponent = 'orchestrator' | 'agent';
13
14
  /** Options for the versioned upgrade command. */
14
15
  interface VersionedUpgradeOptions {
15
16
  platform?: ServicePlatform;
16
- name: string;
17
+ /**
18
+ * Service name. No default — targeting flows through {@link resolveInstance}
19
+ * which consumes `name`, `instanceDir`, or the CWD manifest in priority order.
20
+ */
21
+ name?: string;
22
+ /** Deploy folder of the instance to upgrade. */
23
+ instanceDir?: string;
17
24
  from?: string;
18
25
  url?: string;
19
26
  version?: string;
@@ -22,6 +29,51 @@ interface VersionedUpgradeOptions {
22
29
  rollback?: boolean;
23
30
  force?: boolean;
24
31
  }
32
+ /**
33
+ * Resolved upgrade target: the manifest-backed ServiceConfig the upgrade
34
+ * flow operates on, the manifest's installBase (NOT re-derived from name),
35
+ * and the underlying resolved instance for downstream writes.
36
+ */
37
+ export interface UpgradeTarget {
38
+ config: ServiceConfig;
39
+ installBase: string;
40
+ resolvedInstance: ResolvedInstance;
41
+ }
42
+ /**
43
+ * Resolve the upgrade target via the folder-anchored model and build the
44
+ * ServiceConfig + installBase the rest of the upgrade flow needs.
45
+ *
46
+ * Priority chain (delegated to {@link resolveInstance}):
47
+ * 1. `opts.instanceDir` — read manifest at that path.
48
+ * 2. `opts.name` — match against listInstances() output.
49
+ * 3. CWD manifest — read `./.kici-<component>.json`.
50
+ * 4. otherwise — refuse with a candidate-list error.
51
+ *
52
+ * The returned `installBase` comes from the manifest, NEVER re-derived from
53
+ * the service name. Instances installed with a non-default base must
54
+ * continue to resolve to that base on upgrade.
55
+ */
56
+ export declare function resolveUpgradeTarget(args: {
57
+ component: UpgradeComponent;
58
+ opts: {
59
+ instanceDir?: string;
60
+ name?: string;
61
+ };
62
+ manager: ServiceManager;
63
+ isUserLevel: boolean;
64
+ kiciRoot: string;
65
+ }): Promise<UpgradeTarget>;
66
+ /**
67
+ * Install base for a KiCI component instance.
68
+ *
69
+ * Name-scoped so that two instances of the same component (e.g. an org's
70
+ * dogfood orchestrator and an E2E test orchestrator) own independent
71
+ * versioned trees and symlinks. Per-platform bases:
72
+ * - systemd / compose: /opt/kici/<name>/
73
+ * - launchd: /usr/local/kici/<name>/
74
+ * - windows: C:\Program Files\KiCI\<name>\
75
+ */
76
+ export declare function getInstallBase(platform: ServicePlatform, name: string): string;
25
77
  /**
26
78
  * Perform a versioned directory upgrade for a KiCI component.
27
79
  *
@@ -6,10 +6,10 @@
6
6
  * a container-based service management backend that works on any
7
7
  * platform with Docker or Podman installed.
8
8
  */
9
- import type { ServiceManager, ServiceConfig, ServiceStatus, LogOptions } from './types.js';
9
+ import type { ServiceManager, ServiceConfig, ServiceStatus, LogOptions, DiscoveredInstance } from './types.js';
10
10
  export declare class ComposeServiceManager implements ServiceManager {
11
11
  private runtime;
12
- /** Get the runtime command, detecting it if not already done. */
12
+ /** Get the runtime binary (`podman` or `docker`), detecting it if not already done. */
13
13
  private getRuntime;
14
14
  /** Run a compose command for the given service config. */
15
15
  private runCompose;
@@ -21,5 +21,6 @@ export declare class ComposeServiceManager implements ServiceManager {
21
21
  status(config: ServiceConfig): Promise<ServiceStatus>;
22
22
  logs(config: ServiceConfig, options: LogOptions): Promise<void>;
23
23
  isInstalled(config: ServiceConfig): Promise<boolean>;
24
+ list(isUserLevel: boolean): Promise<DiscoveredInstance[]>;
24
25
  }
25
26
  //# sourceMappingURL=compose.d.ts.map
@@ -8,8 +8,14 @@
8
8
  */
9
9
  export type { ServiceManager, ServiceConfig, ServiceStatus, ServiceState, ServicePlatform, RestartPolicy, LogOptions, } from './types.js';
10
10
  export { DEFAULT_RESTART_POLICY } from './types.js';
11
- export { detectPlatform, isRoot, getConfigDir, getLogDir, getCacheDir } from './platform-detect.js';
11
+ export { detectPlatform, isRoot, kiciConfigRoot, getConfigDir, getLogDir, getCacheDir, } from './platform-detect.js';
12
12
  export { resolveUserLevel, type PrivilegeOpts } from './privilege.js';
13
+ export type { Component, InstanceManifest, IndexEntry, ResolveOptions, ResolvedInstance, } from './instance/types.js';
14
+ export { COMPONENTS, isComponent } from './instance/types.js';
15
+ export { manifestFilename, manifestPath, readManifest, writeManifest, } from './instance/manifest.js';
16
+ export { indexPath, readIndex, writeIndex, appendIndexEntry, removeIndexEntry, } from './instance/index-file.js';
17
+ export { listInstances, resolveInstance, formatRefusal } from './instance/resolve.js';
18
+ export type { ListedInstance, ResolveArgs, ListInstancesArgs } from './instance/resolve.js';
13
19
  import type { ServiceManager, ServicePlatform } from './types.js';
14
20
  /**
15
21
  * Create a ServiceManager for the given platform.
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Instance index — a reconciled CACHE of all installed instances on the host.
3
+ *
4
+ * Lives at <kiciRoot>/instances.json, where kiciRoot is the name-agnostic
5
+ * config root (~/.config/kici/ for user-level, /etc/kici/ for system). The
6
+ * index is convenience: discovery is authoritative against the init system
7
+ * (see resolve.ts#listInstances which reconciles this file against scans).
8
+ *
9
+ * Corrupt index → warn and treat as empty; the next install/uninstall
10
+ * rewrites it cleanly.
11
+ */
12
+ import type { Component, IndexEntry } from './types.js';
13
+ /** Resolve <kiciRoot>/instances.json. */
14
+ export declare function indexPath(kiciRoot: string): string;
15
+ /** Read the index. Missing or corrupt → []. */
16
+ export declare function readIndex(kiciRoot: string): IndexEntry[];
17
+ /** Overwrite the index. */
18
+ export declare function writeIndex(kiciRoot: string, entries: IndexEntry[]): void;
19
+ /**
20
+ * Append an entry. Idempotent for an exact (component,name,instanceDir) match.
21
+ * Throws on a (component,name) collision with a different instanceDir — the
22
+ * caller must use a different name or pass --force to overwrite.
23
+ */
24
+ export declare function appendIndexEntry(kiciRoot: string, entry: IndexEntry): void;
25
+ /** Remove the matching entry (no-op when absent). */
26
+ export declare function removeIndexEntry(kiciRoot: string, key: {
27
+ component: Component;
28
+ name: string;
29
+ }): void;
30
+ //# sourceMappingURL=index-file.d.ts.map
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Instance manifest — the single source of truth for a folder-anchored
3
+ * service install. Written by `install` into the deploy folder, read by
4
+ * every lifecycle command to reconstruct the ServiceConfig.
5
+ */
6
+ import type { Component, InstanceManifest } from './types.js';
7
+ /** Per-component manifest filename. */
8
+ export declare function manifestFilename(component: Component): string;
9
+ /** Resolve the manifest path inside an instance directory. */
10
+ export declare function manifestPath(instanceDir: string, component: Component): string;
11
+ /**
12
+ * Read the manifest for `component` from `instanceDir`.
13
+ * Returns null when the file does not exist; throws on parse or schema errors.
14
+ */
15
+ export declare function readManifest(instanceDir: string, component: Component): InstanceManifest | null;
16
+ /**
17
+ * Write the manifest for `manifest.component` into `instanceDir`.
18
+ * Returns the full path written.
19
+ */
20
+ export declare function writeManifest(instanceDir: string, manifest: InstanceManifest): string;
21
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1,59 @@
1
+ /**
2
+ * resolveInstance — the single entry point every lifecycle command uses to
3
+ * decide which installed service it's operating on.
4
+ *
5
+ * Priority:
6
+ * 1. --instance-dir <path> → read manifest at <path>
7
+ * 2. --name <name> → match against listInstances() result
8
+ * 3. CWD manifest → read ./.kici-<component>.json
9
+ * 4. otherwise → refuse with a candidate list (throws)
10
+ *
11
+ * listInstances reconciles the on-disk index (cache) with the driver's
12
+ * native scan (source of truth). The reconciled result is rewritten back to
13
+ * the index to self-heal stale entries.
14
+ */
15
+ import type { DiscoveredInstance, ServiceManager } from '../types.js';
16
+ import type { Component, ResolveOptions, ResolvedInstance } from './types.js';
17
+ /** A reconciled view of a discovered instance: driver scan + (maybe) index entry. */
18
+ export interface ListedInstance extends DiscoveredInstance {
19
+ instanceDir?: string;
20
+ source: 'index' | 'scan' | 'index+scan';
21
+ }
22
+ export interface ListInstancesArgs {
23
+ component: Component;
24
+ isUserLevel: boolean;
25
+ kiciRoot: string;
26
+ manager: ServiceManager;
27
+ }
28
+ /**
29
+ * Reconcile <kiciRoot>/instances.json with the driver's native scan, then
30
+ * rewrite the index dropping entries whose units no longer exist. Returns
31
+ * the merged list filtered to the requested component + isUserLevel.
32
+ */
33
+ export declare function listInstances(args: ListInstancesArgs): Promise<ListedInstance[]>;
34
+ export interface ResolveArgs {
35
+ component: Component;
36
+ opts: ResolveOptions;
37
+ cwd: string;
38
+ kiciRoot: string;
39
+ manager: ServiceManager;
40
+ /**
41
+ * Privilege scope to resolve against. Must match the caller's resolved
42
+ * --system / --user-level decision so candidate lists and name lookups see
43
+ * the correct set of installed instances.
44
+ */
45
+ isUserLevel: boolean;
46
+ }
47
+ /**
48
+ * Resolve the target instance for the current lifecycle invocation.
49
+ * Throws with a refusal/candidate-listing error when ambiguous.
50
+ */
51
+ export declare function resolveInstance(args: ResolveArgs): Promise<ResolvedInstance>;
52
+ /**
53
+ * Format the refusal message and candidate table.
54
+ *
55
+ * When candidates is empty, returns the "no instances installed" guidance.
56
+ * When candidates exist, lists them with their instanceDir (or "(no manifest)").
57
+ */
58
+ export declare function formatRefusal(component: Component, candidates: ListedInstance[]): string;
59
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Instance types — the shared shape of a folder-anchored service instance,
3
+ * its on-disk manifest, the reconciled cache index, and the per-driver
4
+ * discovery result.
5
+ *
6
+ * A KiCI service instance is identified by (component, name, instanceDir).
7
+ * The deploy folder holds the manifest; the index at <kiciRoot>/instances.json
8
+ * is a reconciled cache of all installed instances on the host.
9
+ */
10
+ import type { ServicePlatform } from '../types.js';
11
+ /** The two KiCI components managed by `kici-admin` service commands. */
12
+ export type Component = 'orchestrator' | 'agent';
13
+ /** Enumerable list — used for iteration and discovery. */
14
+ export declare const COMPONENTS: readonly Component[];
15
+ /** Narrow an arbitrary string to a Component. */
16
+ export declare function isComponent(value: string): value is Component;
17
+ /**
18
+ * The manifest written by `install` into the deploy folder
19
+ * (`./.kici-orchestrator.json` or `./.kici-agent.json`).
20
+ *
21
+ * Holds everything `resolveInstance` needs to reconstruct a ServiceConfig
22
+ * without re-deriving paths.
23
+ */
24
+ export interface InstanceManifest {
25
+ component: Component;
26
+ name: string;
27
+ platform: ServicePlatform;
28
+ isUserLevel: boolean;
29
+ envFilePath: string;
30
+ configDir: string;
31
+ logDir: string;
32
+ installBase: string;
33
+ createdAt: string;
34
+ kiciVersion: string;
35
+ }
36
+ /** A row in `<kiciRoot>/instances.json`. */
37
+ export interface IndexEntry {
38
+ component: Component;
39
+ name: string;
40
+ platform: ServicePlatform;
41
+ isUserLevel: boolean;
42
+ instanceDir: string;
43
+ }
44
+ /** CLI options that influence target resolution. */
45
+ export interface ResolveOptions {
46
+ instanceDir?: string;
47
+ name?: string;
48
+ }
49
+ /** Fully-resolved target — what `resolveInstance` returns. */
50
+ export interface ResolvedInstance {
51
+ manifest: InstanceManifest;
52
+ manifestPath: string;
53
+ instanceDir: string;
54
+ }
55
+ //# sourceMappingURL=types.d.ts.map
@@ -5,7 +5,7 @@
5
5
  * Supports both system-level (/Library/LaunchDaemons/) and
6
6
  * user-level (~/Library/LaunchAgents/) agents.
7
7
  */
8
- import type { ServiceConfig, ServiceManager, ServiceStatus, LogOptions } from './types.js';
8
+ import type { ServiceConfig, ServiceManager, ServiceStatus, LogOptions, DiscoveredInstance } from './types.js';
9
9
  export declare class LaunchdServiceManager implements ServiceManager {
10
10
  /** Build the launchd label for a service. */
11
11
  private label;
@@ -42,6 +42,23 @@ export declare class LaunchdServiceManager implements ServiceManager {
42
42
  /** Is the service currently loaded in its target domain? */
43
43
  private isLoaded;
44
44
  install(config: ServiceConfig): Promise<void>;
45
+ /**
46
+ * Poll until the service is no longer loaded in its target domain, or a
47
+ * short deadline elapses. `launchctl bootout` is asynchronous — it returns
48
+ * before launchd has finished releasing the service — so a bootstrap issued
49
+ * immediately afterward races the teardown and fails with EIO. Waiting for
50
+ * the unload to complete closes that race for the common case; the residual
51
+ * window is covered by bootstrapWithRetry.
52
+ */
53
+ private waitUntilUnloaded;
54
+ /**
55
+ * Bootstrap into the target domain, retrying on the transient EIO
56
+ * ("5: Input/output error") launchd returns when a just-removed service has
57
+ * not finished tearing down. A genuine, non-transient failure (bad plist,
58
+ * permission denied) is re-thrown on the first attempt. If a stale instance
59
+ * reappears between attempts, it is booted out before the next try.
60
+ */
61
+ private bootstrapWithRetry;
45
62
  uninstall(config: ServiceConfig): Promise<void>;
46
63
  start(config: ServiceConfig): Promise<void>;
47
64
  stop(config: ServiceConfig): Promise<void>;
@@ -49,5 +66,6 @@ export declare class LaunchdServiceManager implements ServiceManager {
49
66
  status(config: ServiceConfig): Promise<ServiceStatus>;
50
67
  logs(config: ServiceConfig, options: LogOptions): Promise<void>;
51
68
  isInstalled(config: ServiceConfig): Promise<boolean>;
69
+ list(isUserLevel: boolean): Promise<DiscoveredInstance[]>;
52
70
  }
53
71
  //# sourceMappingURL=launchd.d.ts.map
@@ -25,7 +25,8 @@ export declare function detectPlatform(override?: ServicePlatform): ServicePlatf
25
25
  */
26
26
  export declare function isRoot(): boolean;
27
27
  /**
28
- * Get the configuration directory for a KiCI service.
28
+ * Name-agnostic KiCI config root — the directory that contains every
29
+ * per-instance config subdir for this privilege level.
29
30
  *
30
31
  * Paths follow platform conventions:
31
32
  * - System Linux/macOS: /etc/kici/
@@ -33,18 +34,37 @@ export declare function isRoot(): boolean;
33
34
  * - User macOS: ~/Library/Application Support/kici/
34
35
  * - System Windows: C:\ProgramData\kici\
35
36
  * - User Windows: %LOCALAPPDATA%\kici\
37
+ *
38
+ * Used by the instance index (`<kiciRoot>/instances.json`) which lives
39
+ * outside any per-instance subdir, and as the base for {@link getConfigDir}.
36
40
  */
37
- export declare function getConfigDir(_serviceName: string, isUserLevel: boolean): string;
41
+ export declare function kiciConfigRoot(isUserLevel: boolean): string;
38
42
  /**
39
- * Get the log directory for a KiCI service.
43
+ * Get the configuration directory for a specific KiCI service instance.
40
44
  *
41
- * Paths follow platform conventions:
42
- * - System Linux/macOS: /var/log/kici/
43
- * - User Linux: ~/.local/share/kici/logs/
44
- * - User macOS: ~/Library/Logs/kici/
45
- * - Windows: C:\ProgramData\kici\logs\
45
+ * Returns `<kiciConfigRoot>/<serviceName>/`. The name-scoped subdir is the
46
+ * folder-anchored home for everything belonging to one installed instance
47
+ * (env file, generated unit references, future per-instance state).
48
+ *
49
+ * Examples:
50
+ * - System Linux: /etc/kici/<name>/
51
+ * - User Linux: ~/.config/kici/<name>/
52
+ * - User macOS: ~/Library/Application Support/kici/<name>/
53
+ * - System Windows: C:\ProgramData\kici\<name>\
54
+ * - User Windows: %LOCALAPPDATA%\kici\<name>\
55
+ */
56
+ export declare function getConfigDir(serviceName: string, isUserLevel: boolean): string;
57
+ /**
58
+ * Get the log directory for a specific KiCI service instance.
59
+ *
60
+ * The per-platform layout matches the existing matrix; the service name is
61
+ * injected as the per-instance segment so each instance has its own log dir:
62
+ * - System Linux/macOS: /var/log/kici/<name>/
63
+ * - User Linux: ~/.local/share/kici/<name>/logs/
64
+ * - User macOS: ~/Library/Logs/kici/<name>/
65
+ * - Windows: C:\ProgramData\kici\<name>\logs\
46
66
  */
47
- export declare function getLogDir(_serviceName: string, isUserLevel: boolean): string;
67
+ export declare function getLogDir(serviceName: string, isUserLevel: boolean): string;
48
68
  /**
49
69
  * Get the cache directory for lazy dependency downloads.
50
70
  *
@@ -5,7 +5,7 @@
5
5
  * journalctl, and loginctl commands. Supports both system-level
6
6
  * (/etc/systemd/system/) and user-level (~/.config/systemd/user/) services.
7
7
  */
8
- import type { ServiceConfig, ServiceManager, ServiceStatus, LogOptions } from './types.js';
8
+ import type { DiscoveredInstance, ServiceConfig, ServiceManager, ServiceStatus, LogOptions } from './types.js';
9
9
  /**
10
10
  * Check whether linger is already enabled for a user.
11
11
  *
@@ -37,5 +37,6 @@ export declare class SystemdServiceManager implements ServiceManager {
37
37
  status(config: ServiceConfig): Promise<ServiceStatus>;
38
38
  logs(config: ServiceConfig, options: LogOptions): Promise<void>;
39
39
  isInstalled(config: ServiceConfig): Promise<boolean>;
40
+ list(isUserLevel: boolean): Promise<DiscoveredInstance[]>;
40
41
  }
41
42
  //# sourceMappingURL=systemd.d.ts.map