agent-shim 8.14.0 → 8.15.0
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/README.md +1 -1
- package/dist/cli.cjs +1144 -787
- package/dist/index.cjs +4654 -4223
- package/dist/index.mjs +4628 -4221
- package/dist/types/index.d.ts +2778 -1224
- package/package.json +1 -1
package/dist/types/index.d.ts
CHANGED
|
@@ -3,9 +3,11 @@ import { z } from 'zod';
|
|
|
3
3
|
import { IncomingHttpHeaders, IncomingMessage, ServerResponse } from 'node:http';
|
|
4
4
|
import * as net from 'node:net';
|
|
5
5
|
import { Duplex } from 'node:stream';
|
|
6
|
+
import * as _orpc_client from '@orpc/client';
|
|
6
7
|
import * as zod_v4_core from 'zod/v4/core';
|
|
7
8
|
import * as _orpc_server from '@orpc/server';
|
|
8
|
-
import { RouterClient } from '@orpc/server';
|
|
9
|
+
import { RouterClient, AnyRouter } from '@orpc/server';
|
|
10
|
+
import { RPCLink } from '@orpc/client/fetch';
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
13
|
* Every category a `~/.claude` entry can be classified into. `secret` is deliberately part of this list — it is a real classification the resolver acts on — but it is NOT part of `CategoryMapSchema`'s shape, because no configuration layer may ever toggle it. See OVERRIDABLE_CATEGORIES.
|
|
@@ -766,7 +768,8 @@ interface ClassifyResult {
|
|
|
766
768
|
/** A layer's index in the assembled cascade. Strictly ascending in composition order: a higher id was composed later and therefore wins on the comparator's first rank. */
|
|
767
769
|
type LayerId = number;
|
|
768
770
|
/** Where a cascade layer came from. Purely descriptive — precedence is carried by `LayerId`, never by kind. */
|
|
769
|
-
|
|
771
|
+
declare const LAYER_KINDS: readonly ["global-config", "config-profile", "directory-rule", "portable", "portable-local", "cli-override"];
|
|
772
|
+
type LayerKind = (typeof LAYER_KINDS)[number];
|
|
770
773
|
/** One composable layer of the cascade: its own category toggles and entries overrides, plus the entries key order captured at load time. */
|
|
771
774
|
interface Layer {
|
|
772
775
|
readonly id: LayerId;
|
|
@@ -837,17 +840,8 @@ interface CompiledRule {
|
|
|
837
840
|
readonly matches: (relPath: string) => boolean;
|
|
838
841
|
}
|
|
839
842
|
/** How a decision was reached, for `agent-shim check`'s "which layer decided this" output. */
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
"secret-floor"
|
|
843
|
-
/** Nothing in the classification map recognises the path's top-level entry. */
|
|
844
|
-
| "unclassified"
|
|
845
|
-
/** An entries rule matched and its condition (if any) held. */
|
|
846
|
-
| "entry-rule"
|
|
847
|
-
/** No entries rule survived; a layer's category toggle decided it. */
|
|
848
|
-
| "category-override"
|
|
849
|
-
/** No entries rule and no category toggle; the shipped default for the category decided it. */
|
|
850
|
-
| "category-default";
|
|
843
|
+
declare const DECISION_VIAS: readonly ["secret-floor", "unclassified", "entry-rule", "category-override", "category-default"];
|
|
844
|
+
type DecisionVia = (typeof DECISION_VIAS)[number];
|
|
851
845
|
/** One entry's resolved sharing decision plus the reasoning behind it. */
|
|
852
846
|
interface Decision {
|
|
853
847
|
readonly relPath: string;
|
|
@@ -865,41 +859,11 @@ interface EliminatedRule {
|
|
|
865
859
|
readonly failed: readonly string[];
|
|
866
860
|
}
|
|
867
861
|
/** Every diagnostic the resolver can raise. Codes are stable strings so `agent-shim check` and tests can assert on them. */
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
"EXTENDS_CYCLE"
|
|
871
|
-
/** An `extends` entry names a profile that does not exist. */
|
|
872
|
-
| "MISSING_PROFILE"
|
|
873
|
-
/** An entries key was written under the `secret/` prefix. Rejected at compile time — `secret` can never be overridden by any layer. */
|
|
874
|
-
| "SECRET_ENTRY_KEY"
|
|
875
|
-
/** An entries key under some other prefix matched a path whose real classification is `secret`. Neutralised at resolve time by the floor check. */
|
|
876
|
-
| "SECRET_PATH_NEUTRALISED"
|
|
877
|
-
/** An entries key's declared category prefix disagrees with the real classification of a path it matched. */
|
|
878
|
-
| "CATEGORY_PREFIX_MISMATCH"
|
|
879
|
-
/** An entries key is not of the form `<category>/<path>`. The schema rejects these at parse time; this fires only for a layer built in code. */
|
|
880
|
-
| "MALFORMED_ENTRY_KEY"
|
|
881
|
-
/** An earlier layer's exact key lost to a later layer's glob. Correct per the comparator, but worth surfacing rather than resolving silently. */
|
|
882
|
-
| "EXACT_ENTRY_OVERRIDDEN_BY_LATER_GLOB"
|
|
883
|
-
/** A `history/projects/` pattern's encoded form could plausibly correspond to more than one real path. */
|
|
884
|
-
| "AMBIGUOUS_PROJECT_ENCODING"
|
|
885
|
-
/** A `history/projects/` key's path fragment is neither home-rooted nor absolute, so it cannot be encoded. */
|
|
886
|
-
| "UNROOTED_PROJECT_PATH"
|
|
887
|
-
/** A `~/.claude` entry nothing in the classification map recognises. */
|
|
888
|
-
| "UNCLASSIFIED_ENTRY"
|
|
889
|
-
/** An empty `when: {}` object, which is vacuously true and therefore has no effect. */
|
|
890
|
-
| "EMPTY_WHEN"
|
|
891
|
-
/** The previous farm's manifest is missing or unreadable, so reconciliation ran in conservative mode. */
|
|
892
|
-
| "FARM_MANIFEST_MISSING"
|
|
893
|
-
/** A file Claude Code wrote into a materialised farm directory differs from the canonical copy of the same path. */
|
|
894
|
-
| "RECONCILE_CONFLICT"
|
|
895
|
-
/** Reconciliation proposed adopting a path whose real classification is `secret`. Refused: the secret floor applies to data moving into `~/.claude` exactly as it applies to data moving out. */
|
|
896
|
-
| "RECONCILE_SECRET_BLOCKED"
|
|
897
|
-
/** A previous launch was interrupted mid-swap and this launch completed or undid the half-finished work. */
|
|
898
|
-
| "FARM_SWAP_RECOVERED"
|
|
899
|
-
/** A superseded farm could not be discarded because it still held data the new farm has its own entry for, so it was left on disk for the user to look at. */
|
|
900
|
-
| "FARM_PREVIOUS_RETAINED";
|
|
862
|
+
declare const DIAGNOSTIC_CODES: readonly ["EXTENDS_CYCLE", "MISSING_PROFILE", "SECRET_ENTRY_KEY", "SECRET_PATH_NEUTRALISED", "CATEGORY_PREFIX_MISMATCH", "MALFORMED_ENTRY_KEY", "EXACT_ENTRY_OVERRIDDEN_BY_LATER_GLOB", "AMBIGUOUS_PROJECT_ENCODING", "UNROOTED_PROJECT_PATH", "UNCLASSIFIED_ENTRY", "EMPTY_WHEN", "FARM_MANIFEST_MISSING", "RECONCILE_CONFLICT", "RECONCILE_SECRET_BLOCKED", "FARM_SWAP_RECOVERED", "FARM_PREVIOUS_RETAINED"];
|
|
863
|
+
type DiagnosticCode = (typeof DIAGNOSTIC_CODES)[number];
|
|
901
864
|
/** Severity of a diagnostic. An `error` means a configuration layer asked for something the tool refused to do. */
|
|
902
|
-
|
|
865
|
+
declare const DIAGNOSTIC_SEVERITIES: readonly ["error", "warning", "info"];
|
|
866
|
+
type DiagnosticSeverity = (typeof DIAGNOSTIC_SEVERITIES)[number];
|
|
903
867
|
/** One structured diagnostic. */
|
|
904
868
|
interface Diagnostic {
|
|
905
869
|
readonly code: DiagnosticCode;
|
|
@@ -2222,6 +2186,14 @@ interface HeadroomSocketTrustPorts {
|
|
|
2222
2186
|
/** Stats one path without following symlinks, or returns undefined when nothing is there. */
|
|
2223
2187
|
readonly lstat: (target: string) => SocketPathStat | undefined;
|
|
2224
2188
|
}
|
|
2189
|
+
/** Either a socket path the hop may dial, or the reason it must not: the two never appear together. */
|
|
2190
|
+
type HeadroomSocketTarget = {
|
|
2191
|
+
readonly socketPath: string;
|
|
2192
|
+
readonly refused?: never;
|
|
2193
|
+
} | {
|
|
2194
|
+
readonly refused: string;
|
|
2195
|
+
readonly socketPath?: never;
|
|
2196
|
+
};
|
|
2225
2197
|
|
|
2226
2198
|
/**
|
|
2227
2199
|
* A secondary pre-pipeline surface the listener answers under one path prefix: the typed Remote Control API. The listener owns only the dispatch (the prefix and the not-matched 404); the handle itself is whatever the door built, so this file stays independent of the API framework behind it.
|
|
@@ -2239,6 +2211,8 @@ interface PrePipelineApi {
|
|
|
2239
2211
|
* The Remote Control operations as a typed oRPC API, so programmatic consumers (automation, a mobile or web client, another of this user's tools) get a generated type-safe client instead of hand-rolled HTTP. One procedure per existing operation, each wrapping the same operation the bespoke token-gated routes wrap (the routes stay: the CLI uses them), with inputs and outputs validating through the Zod schemas of `rcSchemas.ts`, which the operations' own values must satisfy, so contract and behaviour share one schema source and cannot drift apart silently.
|
|
2240
2212
|
*
|
|
2241
2213
|
* Mounted on the provider listener beside the bespoke namespace, authenticated by the same per-generation owner-only control token as a Bearer credential: a fresh random value per door start, written owner-only under the front door's state directory, and checked in constant time like every other capability the door accepts. `rc.subscribe` streams the client attachment's fan-out: every event the door's held stream produced, SSE-framed by oRPC's event iterator, each carrying its sequence number as the SSE event id so a consumer's own reconnect can resume exactly as the door's does.
|
|
2214
|
+
*
|
|
2215
|
+
* This module also owns the mount's router-agnostic plumbing, which the control-plane routers (`controlApi.ts`) serve on the same prefix under the same token: the control-token middleware (`doorApiAuth`), the node-handler builder (`doorApiNodeHandlerOf`) and the TLS-pinned client link (`frontDoorApiLink`).
|
|
2242
2216
|
*/
|
|
2243
2217
|
/** The one path prefix the typed API is mounted under, answered before the routed pipeline like the bespoke control routes are. */
|
|
2244
2218
|
declare const RC_ORPC_PATH_PREFIX = "/__agent-shim/orpc";
|
|
@@ -2265,29 +2239,23 @@ interface RcApiDeps {
|
|
|
2265
2239
|
/** The client attachment's fan-out, whose events the subscription yields. */
|
|
2266
2240
|
readonly fanout: RcEventFanout;
|
|
2267
2241
|
}
|
|
2242
|
+
/** The context every procedure on the door's typed API runs in: the request's own headers, which the control-token middleware reads the Bearer credential from. */
|
|
2243
|
+
interface DoorApiContext {
|
|
2244
|
+
readonly headers: IncomingHttpHeaders;
|
|
2245
|
+
}
|
|
2246
|
+
/** Builds the middleware every procedure on the door's typed API sits behind, whichever router it belongs to: the per-generation owner-only control token, presented as a Bearer credential and checked in constant time like every other capability the door accepts. */
|
|
2247
|
+
declare function doorApiAuth(expectedToken: string): _orpc_server.BuilderWithMiddlewares<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, Schema<unknown, unknown>, Schema<unknown, unknown>, Record<never, never>, Record<never, never>>;
|
|
2268
2248
|
/** Builds the typed API's router: one procedure per operation, every one behind the control-token middleware. */
|
|
2269
2249
|
declare function createRcApiRouter(deps: RcApiDeps): {
|
|
2270
2250
|
rc: {
|
|
2271
|
-
list: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<{
|
|
2272
|
-
readonly headers: IncomingHttpHeaders;
|
|
2273
|
-
} & Record<never, never>, {
|
|
2274
|
-
readonly headers: IncomingHttpHeaders;
|
|
2275
|
-
}, {
|
|
2276
|
-
readonly headers: IncomingHttpHeaders;
|
|
2277
|
-
}>, any, Schema<unknown, unknown>, zod.ZodObject<{
|
|
2251
|
+
list: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, Schema<unknown, unknown>, zod.ZodObject<{
|
|
2278
2252
|
sessions: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
2279
2253
|
id: zod.ZodString;
|
|
2280
2254
|
createdAt: zod.ZodNumber;
|
|
2281
2255
|
lastSeenAt: zod.ZodNumber;
|
|
2282
2256
|
}, zod_v4_core.$strict>>>;
|
|
2283
2257
|
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
2284
|
-
status: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<{
|
|
2285
|
-
readonly headers: IncomingHttpHeaders;
|
|
2286
|
-
} & Record<never, never>, {
|
|
2287
|
-
readonly headers: IncomingHttpHeaders;
|
|
2288
|
-
}, {
|
|
2289
|
-
readonly headers: IncomingHttpHeaders;
|
|
2290
|
-
}>, any, zod.ZodObject<{
|
|
2258
|
+
status: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
2291
2259
|
session: zod.ZodOptional<zod.ZodString>;
|
|
2292
2260
|
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
2293
2261
|
statuses: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
@@ -2311,13 +2279,7 @@ declare function createRcApiRouter(deps: RcApiDeps): {
|
|
|
2311
2279
|
lastSeenAt: zod.ZodNumber;
|
|
2312
2280
|
}, zod_v4_core.$strict>>>;
|
|
2313
2281
|
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
2314
|
-
pending: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<{
|
|
2315
|
-
readonly headers: IncomingHttpHeaders;
|
|
2316
|
-
} & Record<never, never>, {
|
|
2317
|
-
readonly headers: IncomingHttpHeaders;
|
|
2318
|
-
}, {
|
|
2319
|
-
readonly headers: IncomingHttpHeaders;
|
|
2320
|
-
}>, any, zod.ZodObject<{
|
|
2282
|
+
pending: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
2321
2283
|
session: zod.ZodOptional<zod.ZodString>;
|
|
2322
2284
|
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
2323
2285
|
pending: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
@@ -2328,26 +2290,14 @@ declare function createRcApiRouter(deps: RcApiDeps): {
|
|
|
2328
2290
|
observedAt: zod.ZodNumber;
|
|
2329
2291
|
}, zod_v4_core.$strict>>>;
|
|
2330
2292
|
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
2331
|
-
send: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<{
|
|
2332
|
-
readonly headers: IncomingHttpHeaders;
|
|
2333
|
-
} & Record<never, never>, {
|
|
2334
|
-
readonly headers: IncomingHttpHeaders;
|
|
2335
|
-
}, {
|
|
2336
|
-
readonly headers: IncomingHttpHeaders;
|
|
2337
|
-
}>, any, zod.ZodObject<{
|
|
2293
|
+
send: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
2338
2294
|
session: zod.ZodString;
|
|
2339
2295
|
text: zod.ZodString;
|
|
2340
2296
|
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
2341
2297
|
session: zod.ZodString;
|
|
2342
2298
|
sequenceNums: zod.ZodReadonly<zod.ZodArray<zod.ZodNumber>>;
|
|
2343
2299
|
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
2344
|
-
answer: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<{
|
|
2345
|
-
readonly headers: IncomingHttpHeaders;
|
|
2346
|
-
} & Record<never, never>, {
|
|
2347
|
-
readonly headers: IncomingHttpHeaders;
|
|
2348
|
-
}, {
|
|
2349
|
-
readonly headers: IncomingHttpHeaders;
|
|
2350
|
-
}>, any, zod.ZodObject<{
|
|
2300
|
+
answer: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
2351
2301
|
session: zod.ZodString;
|
|
2352
2302
|
request: zod.ZodString;
|
|
2353
2303
|
approve: zod.ZodBoolean;
|
|
@@ -2357,38 +2307,20 @@ declare function createRcApiRouter(deps: RcApiDeps): {
|
|
|
2357
2307
|
request: zod.ZodString;
|
|
2358
2308
|
sequenceNums: zod.ZodReadonly<zod.ZodArray<zod.ZodNumber>>;
|
|
2359
2309
|
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
2360
|
-
interrupt: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<{
|
|
2361
|
-
readonly headers: IncomingHttpHeaders;
|
|
2362
|
-
} & Record<never, never>, {
|
|
2363
|
-
readonly headers: IncomingHttpHeaders;
|
|
2364
|
-
}, {
|
|
2365
|
-
readonly headers: IncomingHttpHeaders;
|
|
2366
|
-
}>, any, zod.ZodObject<{
|
|
2310
|
+
interrupt: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
2367
2311
|
session: zod.ZodString;
|
|
2368
2312
|
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
2369
2313
|
session: zod.ZodString;
|
|
2370
2314
|
sequenceNums: zod.ZodReadonly<zod.ZodArray<zod.ZodNumber>>;
|
|
2371
2315
|
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
2372
|
-
setModel: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<{
|
|
2373
|
-
readonly headers: IncomingHttpHeaders;
|
|
2374
|
-
} & Record<never, never>, {
|
|
2375
|
-
readonly headers: IncomingHttpHeaders;
|
|
2376
|
-
}, {
|
|
2377
|
-
readonly headers: IncomingHttpHeaders;
|
|
2378
|
-
}>, any, zod.ZodObject<{
|
|
2316
|
+
setModel: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
2379
2317
|
session: zod.ZodString;
|
|
2380
2318
|
model: zod.ZodString;
|
|
2381
2319
|
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
2382
2320
|
session: zod.ZodString;
|
|
2383
2321
|
sequenceNums: zod.ZodReadonly<zod.ZodArray<zod.ZodNumber>>;
|
|
2384
2322
|
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
2385
|
-
setPermissionMode: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<{
|
|
2386
|
-
readonly headers: IncomingHttpHeaders;
|
|
2387
|
-
} & Record<never, never>, {
|
|
2388
|
-
readonly headers: IncomingHttpHeaders;
|
|
2389
|
-
}, {
|
|
2390
|
-
readonly headers: IncomingHttpHeaders;
|
|
2391
|
-
}>, any, zod.ZodObject<{
|
|
2323
|
+
setPermissionMode: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
2392
2324
|
session: zod.ZodString;
|
|
2393
2325
|
mode: zod.ZodEnum<{
|
|
2394
2326
|
default: "default";
|
|
@@ -2402,13 +2334,7 @@ declare function createRcApiRouter(deps: RcApiDeps): {
|
|
|
2402
2334
|
session: zod.ZodString;
|
|
2403
2335
|
sequenceNums: zod.ZodReadonly<zod.ZodArray<zod.ZodNumber>>;
|
|
2404
2336
|
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
2405
|
-
subscribe: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<{
|
|
2406
|
-
readonly headers: IncomingHttpHeaders;
|
|
2407
|
-
} & Record<never, never>, {
|
|
2408
|
-
readonly headers: IncomingHttpHeaders;
|
|
2409
|
-
}, {
|
|
2410
|
-
readonly headers: IncomingHttpHeaders;
|
|
2411
|
-
}>, any, zod.ZodObject<{
|
|
2337
|
+
subscribe: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
2412
2338
|
session: zod.ZodOptional<zod.ZodString>;
|
|
2413
2339
|
}, zod_v4_core.$strict>, any, Record<never, never>, Record<never, never>>;
|
|
2414
2340
|
};
|
|
@@ -2416,197 +2342,854 @@ declare function createRcApiRouter(deps: RcApiDeps): {
|
|
|
2416
2342
|
/** The typed API's router, as the CLI-side client's own type is derived from it. */
|
|
2417
2343
|
type RcApiRouter = ReturnType<typeof createRcApiRouter>;
|
|
2418
2344
|
/**
|
|
2419
|
-
* Builds the
|
|
2345
|
+
* Builds the node handler that serves one router of the door's typed API under the mount's one prefix: the pre-pipeline surface the provider listener hands every request under `RC_ORPC_PATH_PREFIX`, answering with `matched: false` for a path under the prefix that names no procedure (which the listener itself answers as a 404). Request bodies are bounded by the same protocol cap the bespoke routes apply. Every router the mount serves (Remote Control and the control plane) goes through this one builder, so the prefix, the context and the cap are stated once.
|
|
2346
|
+
*/
|
|
2347
|
+
declare function doorApiNodeHandlerOf(router: AnyRouter): PrePipelineApi;
|
|
2348
|
+
/**
|
|
2349
|
+
* Builds the typed API's node handler for the Remote Control router alone: the pre-pipeline surface the provider listener hands every request under `RC_ORPC_PATH_PREFIX`.
|
|
2420
2350
|
*/
|
|
2421
2351
|
declare function createRcApiNodeHandler(deps: RcApiDeps): PrePipelineApi;
|
|
2422
2352
|
/** The typed API's client as the `frontdoor rc` verbs use it: every call presents the control token, over TLS trusting only the CA file the door's own state names. */
|
|
2423
2353
|
type RcApiClient = RouterClient<RcApiRouter>;
|
|
2354
|
+
/** Builds the link every client of the door's typed API dials through: the door's address under the mount prefix, the per-generation control token on every call, and TLS trusting only the CA the door's own state names. */
|
|
2355
|
+
declare function frontDoorApiLink(port: number, ca: string, token: string): RPCLink<_orpc_client.ClientContext>;
|
|
2424
2356
|
/** Builds the typed API's client for the door's provider listener: the same address, CA and per-generation control token the bespoke control client uses. */
|
|
2425
2357
|
declare function frontDoorRcApiClient(port: number, ca: string, token: string): RcApiClient;
|
|
2426
2358
|
|
|
2427
2359
|
/**
|
|
2428
|
-
* The
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2360
|
+
* The Zod schema of `agent-shim check --json`'s output: one definition of the report's wire shape, so the JSON conversion (`checkReportToJson`, whose return type is this schema's inferred type, which makes the compiler prove the two agree) and every programmatic consumer of the report (the front door's `check.run` procedure above all) validate through the same source. A plain Zod leaf mirroring the shapes the report's own modules define; the vocabularies it switches on (layer kinds, decision routes, diagnostic codes and severities, decision sources) are imported as const arrays from those modules rather than restated here, so a vocabulary added there is a compile error here until this schema names it.
|
|
2361
|
+
*/
|
|
2362
|
+
/** Which credential a launch would use, as the report's own credential block states it. */
|
|
2363
|
+
declare const CHECK_CREDENTIAL_APPLIES: readonly ["provider", "identity", "stored-login"];
|
|
2364
|
+
/** Everything `agent-shim check` reports about one directory, as `check --json` prints it and the door's `check.run` procedure returns it. */
|
|
2365
|
+
declare const CheckReportJsonSchema: z.ZodObject<{
|
|
2366
|
+
identity: z.ZodObject<{
|
|
2367
|
+
name: z.ZodNullable<z.ZodString>;
|
|
2368
|
+
source: z.ZodEnum<{
|
|
2369
|
+
"config-dir-escape-hatch": "config-dir-escape-hatch";
|
|
2370
|
+
argv: "argv";
|
|
2371
|
+
env: "env";
|
|
2372
|
+
"directory-pin": "directory-pin";
|
|
2373
|
+
"active-identity-file": "active-identity-file";
|
|
2374
|
+
none: "none";
|
|
2375
|
+
}>;
|
|
2376
|
+
}, z.core.$strict>;
|
|
2377
|
+
pool: z.ZodOptional<z.ZodObject<{
|
|
2378
|
+
pool: z.ZodString;
|
|
2379
|
+
directory: z.ZodString;
|
|
2380
|
+
pick: z.ZodOptional<z.ZodString>;
|
|
2381
|
+
candidates: z.ZodArray<z.ZodObject<{
|
|
2382
|
+
identity: z.ZodString;
|
|
2383
|
+
class: z.ZodEnum<{
|
|
2384
|
+
unknown: "unknown";
|
|
2385
|
+
scored: "scored";
|
|
2386
|
+
"pay-per-use": "pay-per-use";
|
|
2387
|
+
ineligible: "ineligible";
|
|
2388
|
+
}>;
|
|
2389
|
+
score: z.ZodOptional<z.ZodNumber>;
|
|
2390
|
+
feasible: z.ZodBoolean;
|
|
2391
|
+
blockedUntil: z.ZodOptional<z.ZodISODateTime>;
|
|
2392
|
+
plan: z.ZodUnion<readonly [z.ZodObject<{
|
|
2393
|
+
kind: z.ZodLiteral<"subscription">;
|
|
2394
|
+
capacity: z.ZodNumber;
|
|
2395
|
+
recognised: z.ZodBoolean;
|
|
2396
|
+
tier: z.ZodOptional<z.ZodString>;
|
|
2397
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2398
|
+
kind: z.ZodLiteral<"pay-per-use">;
|
|
2399
|
+
tier: z.ZodOptional<z.ZodString>;
|
|
2400
|
+
}, z.core.$strict>]>;
|
|
2401
|
+
reasons: z.ZodArray<z.ZodString>;
|
|
2402
|
+
}, z.core.$strict>>;
|
|
2403
|
+
missing: z.ZodArray<z.ZodString>;
|
|
2404
|
+
earliestReturn: z.ZodOptional<z.ZodObject<{
|
|
2405
|
+
identity: z.ZodString;
|
|
2406
|
+
at: z.ZodISODateTime;
|
|
2407
|
+
}, z.core.$strict>>;
|
|
2408
|
+
stickyProblem: z.ZodOptional<z.ZodString>;
|
|
2409
|
+
}, z.core.$strict>>;
|
|
2410
|
+
configProfile: z.ZodObject<{
|
|
2411
|
+
name: z.ZodNullable<z.ZodString>;
|
|
2412
|
+
source: z.ZodEnum<{
|
|
2413
|
+
"directory-rule": "directory-rule";
|
|
2414
|
+
env: "env";
|
|
2415
|
+
none: "none";
|
|
2416
|
+
"cli-flag": "cli-flag";
|
|
2417
|
+
"identity-default": "identity-default";
|
|
2418
|
+
"global-default": "global-default";
|
|
2419
|
+
}>;
|
|
2420
|
+
}, z.core.$strict>;
|
|
2421
|
+
layers: z.ZodReadonly<z.ZodArray<z.ZodObject<{
|
|
2422
|
+
id: z.ZodInt;
|
|
2423
|
+
kind: z.ZodEnum<{
|
|
2424
|
+
"global-config": "global-config";
|
|
2425
|
+
"config-profile": "config-profile";
|
|
2426
|
+
"directory-rule": "directory-rule";
|
|
2427
|
+
portable: "portable";
|
|
2428
|
+
"portable-local": "portable-local";
|
|
2429
|
+
"cli-override": "cli-override";
|
|
2430
|
+
}>;
|
|
2431
|
+
source: z.ZodString;
|
|
2432
|
+
}, z.core.$strict>>>;
|
|
2433
|
+
entries: z.ZodReadonly<z.ZodArray<z.ZodObject<{
|
|
2434
|
+
path: z.ZodString;
|
|
2435
|
+
shared: z.ZodBoolean;
|
|
2436
|
+
via: z.ZodEnum<{
|
|
2437
|
+
"secret-floor": "secret-floor";
|
|
2438
|
+
unclassified: "unclassified";
|
|
2439
|
+
"entry-rule": "entry-rule";
|
|
2440
|
+
"category-override": "category-override";
|
|
2441
|
+
"category-default": "category-default";
|
|
2442
|
+
}>;
|
|
2443
|
+
category: z.ZodNullable<z.ZodEnum<{
|
|
2444
|
+
secret: "secret";
|
|
2445
|
+
runtime: "runtime";
|
|
2446
|
+
history: "history";
|
|
2447
|
+
knowledge: "knowledge";
|
|
2448
|
+
settings: "settings";
|
|
2449
|
+
}>>;
|
|
2450
|
+
rule: z.ZodOptional<z.ZodObject<{
|
|
2451
|
+
key: z.ZodString;
|
|
2452
|
+
layer: z.ZodInt;
|
|
2453
|
+
}, z.core.$strict>>;
|
|
2454
|
+
eliminated: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodObject<{
|
|
2455
|
+
key: z.ZodString;
|
|
2456
|
+
failed: z.ZodReadonly<z.ZodArray<z.ZodString>>;
|
|
2457
|
+
}, z.core.$strict>>>>;
|
|
2458
|
+
}, z.core.$strict>>>;
|
|
2459
|
+
projectEncodingAmbiguities: z.ZodReadonly<z.ZodArray<z.ZodObject<{
|
|
2460
|
+
fragment: z.ZodString;
|
|
2461
|
+
encoded: z.ZodString;
|
|
2462
|
+
reason: z.ZodEnum<{
|
|
2463
|
+
"lossy-characters": "lossy-characters";
|
|
2464
|
+
"collides-with-sibling-pattern": "collides-with-sibling-pattern";
|
|
2465
|
+
}>;
|
|
2466
|
+
detail: z.ZodString;
|
|
2467
|
+
}, z.core.$strict>>>;
|
|
2468
|
+
diagnostics: z.ZodReadonly<z.ZodArray<z.ZodObject<{
|
|
2469
|
+
code: z.ZodEnum<{
|
|
2470
|
+
EXTENDS_CYCLE: "EXTENDS_CYCLE";
|
|
2471
|
+
MISSING_PROFILE: "MISSING_PROFILE";
|
|
2472
|
+
SECRET_ENTRY_KEY: "SECRET_ENTRY_KEY";
|
|
2473
|
+
SECRET_PATH_NEUTRALISED: "SECRET_PATH_NEUTRALISED";
|
|
2474
|
+
CATEGORY_PREFIX_MISMATCH: "CATEGORY_PREFIX_MISMATCH";
|
|
2475
|
+
MALFORMED_ENTRY_KEY: "MALFORMED_ENTRY_KEY";
|
|
2476
|
+
EXACT_ENTRY_OVERRIDDEN_BY_LATER_GLOB: "EXACT_ENTRY_OVERRIDDEN_BY_LATER_GLOB";
|
|
2477
|
+
AMBIGUOUS_PROJECT_ENCODING: "AMBIGUOUS_PROJECT_ENCODING";
|
|
2478
|
+
UNROOTED_PROJECT_PATH: "UNROOTED_PROJECT_PATH";
|
|
2479
|
+
UNCLASSIFIED_ENTRY: "UNCLASSIFIED_ENTRY";
|
|
2480
|
+
EMPTY_WHEN: "EMPTY_WHEN";
|
|
2481
|
+
FARM_MANIFEST_MISSING: "FARM_MANIFEST_MISSING";
|
|
2482
|
+
RECONCILE_CONFLICT: "RECONCILE_CONFLICT";
|
|
2483
|
+
RECONCILE_SECRET_BLOCKED: "RECONCILE_SECRET_BLOCKED";
|
|
2484
|
+
FARM_SWAP_RECOVERED: "FARM_SWAP_RECOVERED";
|
|
2485
|
+
FARM_PREVIOUS_RETAINED: "FARM_PREVIOUS_RETAINED";
|
|
2486
|
+
}>;
|
|
2487
|
+
severity: z.ZodEnum<{
|
|
2488
|
+
error: "error";
|
|
2489
|
+
warning: "warning";
|
|
2490
|
+
info: "info";
|
|
2491
|
+
}>;
|
|
2492
|
+
message: z.ZodString;
|
|
2493
|
+
subject: z.ZodOptional<z.ZodString>;
|
|
2494
|
+
layer: z.ZodOptional<z.ZodInt>;
|
|
2495
|
+
}, z.core.$strict>>>;
|
|
2496
|
+
ambientCredential: z.ZodUnion<readonly [z.ZodObject<{
|
|
2497
|
+
ok: z.ZodLiteral<true>;
|
|
2498
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2499
|
+
ok: z.ZodLiteral<false>;
|
|
2500
|
+
variable: z.ZodString;
|
|
2501
|
+
message: z.ZodString;
|
|
2502
|
+
}, z.core.$strict>]>;
|
|
2503
|
+
keychain: z.ZodOptional<z.ZodObject<{
|
|
2504
|
+
checked: z.ZodLiteral<true>;
|
|
2505
|
+
found: z.ZodBoolean;
|
|
2506
|
+
serviceName: z.ZodOptional<z.ZodString>;
|
|
2507
|
+
note: z.ZodString;
|
|
2508
|
+
}, z.core.$strict>>;
|
|
2509
|
+
settingsExposure: z.ZodReadonly<z.ZodArray<z.ZodObject<{
|
|
2510
|
+
file: z.ZodString;
|
|
2511
|
+
envKeyNames: z.ZodReadonly<z.ZodArray<z.ZodString>>;
|
|
2512
|
+
hookEventNames: z.ZodReadonly<z.ZodArray<z.ZodString>>;
|
|
2513
|
+
hookCommandCount: z.ZodInt;
|
|
2514
|
+
}, z.core.$strict>>>;
|
|
2515
|
+
credential: z.ZodObject<{
|
|
2516
|
+
applies: z.ZodEnum<{
|
|
2517
|
+
identity: "identity";
|
|
2518
|
+
provider: "provider";
|
|
2519
|
+
"stored-login": "stored-login";
|
|
2520
|
+
}>;
|
|
2521
|
+
provider: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
2522
|
+
name: z.ZodString;
|
|
2523
|
+
credential: z.ZodObject<{
|
|
2524
|
+
target: z.ZodEnum<{
|
|
2525
|
+
bearer: "bearer";
|
|
2526
|
+
apiKey: "apiKey";
|
|
2527
|
+
oauthToken: "oauthToken";
|
|
2528
|
+
}>;
|
|
2529
|
+
sources: z.ZodReadonly<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
2530
|
+
kind: z.ZodLiteral<"env">;
|
|
2531
|
+
variable: z.ZodString;
|
|
2532
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2533
|
+
kind: z.ZodLiteral<"file">;
|
|
2534
|
+
path: z.ZodString;
|
|
2535
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2536
|
+
kind: z.ZodLiteral<"command">;
|
|
2537
|
+
program: z.ZodString;
|
|
2538
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2539
|
+
kind: z.ZodLiteral<"op">;
|
|
2540
|
+
reference: z.ZodString;
|
|
2541
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2542
|
+
kind: z.ZodLiteral<"keychain">;
|
|
2543
|
+
service: z.ZodString;
|
|
2544
|
+
account: z.ZodOptional<z.ZodString>;
|
|
2545
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2546
|
+
kind: z.ZodLiteral<"literal">;
|
|
2547
|
+
}, z.core.$strict>]>>>;
|
|
2548
|
+
cache: z.ZodOptional<z.ZodObject<{
|
|
2549
|
+
ttl: z.ZodOptional<z.ZodString>;
|
|
2550
|
+
store: z.ZodOptional<z.ZodEnum<{
|
|
2551
|
+
file: "file";
|
|
2552
|
+
keychain: "keychain";
|
|
2553
|
+
}>>;
|
|
2554
|
+
}, z.core.$strict>>;
|
|
2555
|
+
}, z.core.$strict>;
|
|
2556
|
+
cached: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
2557
|
+
store: z.ZodEnum<{
|
|
2558
|
+
file: "file";
|
|
2559
|
+
keychain: "keychain";
|
|
2560
|
+
}>;
|
|
2561
|
+
status: z.ZodLiteral<"empty">;
|
|
2562
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2563
|
+
store: z.ZodEnum<{
|
|
2564
|
+
file: "file";
|
|
2565
|
+
keychain: "keychain";
|
|
2566
|
+
}>;
|
|
2567
|
+
status: z.ZodLiteral<"unreadable">;
|
|
2568
|
+
reason: z.ZodString;
|
|
2569
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2570
|
+
store: z.ZodEnum<{
|
|
2571
|
+
file: "file";
|
|
2572
|
+
keychain: "keychain";
|
|
2573
|
+
}>;
|
|
2574
|
+
status: z.ZodEnum<{
|
|
2575
|
+
fresh: "fresh";
|
|
2576
|
+
expired: "expired";
|
|
2577
|
+
}>;
|
|
2578
|
+
ageMs: z.ZodNumber;
|
|
2579
|
+
expiresInMs: z.ZodOptional<z.ZodNumber>;
|
|
2580
|
+
}, z.core.$strict>]>>;
|
|
2581
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2582
|
+
name: z.ZodString;
|
|
2583
|
+
problem: z.ZodString;
|
|
2584
|
+
}, z.core.$strict>]>>;
|
|
2585
|
+
identity: z.ZodOptional<z.ZodObject<{
|
|
2586
|
+
target: z.ZodEnum<{
|
|
2587
|
+
bearer: "bearer";
|
|
2588
|
+
apiKey: "apiKey";
|
|
2589
|
+
oauthToken: "oauthToken";
|
|
2590
|
+
}>;
|
|
2591
|
+
sources: z.ZodReadonly<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
2592
|
+
kind: z.ZodLiteral<"env">;
|
|
2593
|
+
variable: z.ZodString;
|
|
2594
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2595
|
+
kind: z.ZodLiteral<"file">;
|
|
2596
|
+
path: z.ZodString;
|
|
2597
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2598
|
+
kind: z.ZodLiteral<"command">;
|
|
2599
|
+
program: z.ZodString;
|
|
2600
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2601
|
+
kind: z.ZodLiteral<"op">;
|
|
2602
|
+
reference: z.ZodString;
|
|
2603
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2604
|
+
kind: z.ZodLiteral<"keychain">;
|
|
2605
|
+
service: z.ZodString;
|
|
2606
|
+
account: z.ZodOptional<z.ZodString>;
|
|
2607
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2608
|
+
kind: z.ZodLiteral<"literal">;
|
|
2609
|
+
}, z.core.$strict>]>>>;
|
|
2610
|
+
cache: z.ZodOptional<z.ZodObject<{
|
|
2611
|
+
ttl: z.ZodOptional<z.ZodString>;
|
|
2612
|
+
store: z.ZodOptional<z.ZodEnum<{
|
|
2613
|
+
file: "file";
|
|
2614
|
+
keychain: "keychain";
|
|
2615
|
+
}>>;
|
|
2616
|
+
}, z.core.$strict>>;
|
|
2617
|
+
}, z.core.$strict>>;
|
|
2618
|
+
identityCached: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
2619
|
+
store: z.ZodEnum<{
|
|
2620
|
+
file: "file";
|
|
2621
|
+
keychain: "keychain";
|
|
2622
|
+
}>;
|
|
2623
|
+
status: z.ZodLiteral<"empty">;
|
|
2624
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2625
|
+
store: z.ZodEnum<{
|
|
2626
|
+
file: "file";
|
|
2627
|
+
keychain: "keychain";
|
|
2628
|
+
}>;
|
|
2629
|
+
status: z.ZodLiteral<"unreadable">;
|
|
2630
|
+
reason: z.ZodString;
|
|
2631
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2632
|
+
store: z.ZodEnum<{
|
|
2633
|
+
file: "file";
|
|
2634
|
+
keychain: "keychain";
|
|
2635
|
+
}>;
|
|
2636
|
+
status: z.ZodEnum<{
|
|
2637
|
+
fresh: "fresh";
|
|
2638
|
+
expired: "expired";
|
|
2639
|
+
}>;
|
|
2640
|
+
ageMs: z.ZodNumber;
|
|
2641
|
+
expiresInMs: z.ZodOptional<z.ZodNumber>;
|
|
2642
|
+
}, z.core.$strict>]>>;
|
|
2643
|
+
}, z.core.$strict>;
|
|
2644
|
+
claudeVersion: z.ZodOptional<z.ZodObject<{
|
|
2645
|
+
pinned: z.ZodOptional<z.ZodObject<{
|
|
2646
|
+
version: z.ZodString;
|
|
2647
|
+
source: z.ZodEnum<{
|
|
2648
|
+
flag: "flag";
|
|
2649
|
+
environment: "environment";
|
|
2650
|
+
cascade: "cascade";
|
|
2651
|
+
}>;
|
|
2652
|
+
installed: z.ZodBoolean;
|
|
2653
|
+
}, z.core.$strict>>;
|
|
2654
|
+
highestInstalled: z.ZodOptional<z.ZodString>;
|
|
2655
|
+
installed: z.ZodReadonly<z.ZodArray<z.ZodString>>;
|
|
2656
|
+
}, z.core.$strict>>;
|
|
2657
|
+
}, z.core.$strict>;
|
|
2658
|
+
type CheckReportJson = z.output<typeof CheckReportJsonSchema>;
|
|
2659
|
+
|
|
2660
|
+
/** What a cache stores for one credential: the token, when it was fetched, and the source that produced it (a non-secret descriptor, kept so `check` and the launch log can still say where the token came from). */
|
|
2661
|
+
declare const CachedCredentialSchema: z.ZodObject<{
|
|
2662
|
+
token: z.ZodString;
|
|
2663
|
+
fetchedAt: z.ZodNumber;
|
|
2664
|
+
source: z.ZodUnion<readonly [z.ZodObject<{
|
|
2665
|
+
env: z.ZodString;
|
|
2666
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2667
|
+
file: z.ZodString;
|
|
2668
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2669
|
+
interactive: z.ZodOptional<z.ZodBoolean>;
|
|
2670
|
+
timeoutMs: z.ZodOptional<z.ZodInt>;
|
|
2671
|
+
command: z.ZodTuple<[z.ZodString], z.ZodString>;
|
|
2672
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2673
|
+
interactive: z.ZodOptional<z.ZodBoolean>;
|
|
2674
|
+
timeoutMs: z.ZodOptional<z.ZodInt>;
|
|
2675
|
+
op: z.ZodString;
|
|
2676
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2677
|
+
interactive: z.ZodOptional<z.ZodBoolean>;
|
|
2678
|
+
timeoutMs: z.ZodOptional<z.ZodInt>;
|
|
2679
|
+
keychain: z.ZodObject<{
|
|
2680
|
+
service: z.ZodString;
|
|
2681
|
+
account: z.ZodOptional<z.ZodString>;
|
|
2682
|
+
}, z.core.$strict>;
|
|
2683
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2684
|
+
literal: z.ZodString;
|
|
2685
|
+
}, z.core.$strict>]>;
|
|
2686
|
+
}, z.core.$strict>;
|
|
2687
|
+
type CachedCredential = z.infer<typeof CachedCredentialSchema>;
|
|
2452
2688
|
/**
|
|
2453
|
-
*
|
|
2689
|
+
* Where cached credentials live, injected so resolution and its tests need neither the Keychain nor a real directory. `owner` names what the credential belongs to (`identity work`, `provider z`) and is the entry's key; `store` picks the backing store. `read` returns undefined for a missing or unreadable entry, since an entry that cannot be used is the same as no entry.
|
|
2454
2690
|
*/
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
readonly
|
|
2459
|
-
readonly refreshToken: string;
|
|
2460
|
-
readonly organizationUuid: string;
|
|
2461
|
-
readonly accountUuid: string;
|
|
2462
|
-
}
|
|
2463
|
-
/** Everything the service needs, injected so the decision logic runs against fakes in unit tests. */
|
|
2464
|
-
interface RcSelfHostDeps {
|
|
2465
|
-
readonly now: () => number;
|
|
2466
|
-
/** Mints the session and event ids: a v4 UUID or better in production. */
|
|
2467
|
-
readonly newUuid: () => string;
|
|
2468
|
-
/** Mints opaque token material (the worker JWTs): cryptographically random in production. */
|
|
2469
|
-
readonly randomToken: () => string;
|
|
2470
|
-
/** The minted credential this door authenticates against, read fresh so a re-mint takes effect without restarting the door; undefined while none was ever minted, in which case every authenticated call is refused. */
|
|
2471
|
-
readonly credentialRecord: () => RcSelfHostCredentialRecord | undefined;
|
|
2472
|
-
readonly log?: (line: string) => void;
|
|
2473
|
-
}
|
|
2474
|
-
/** The self-hosted Remote Control service: the session-family route for the pipeline, and the local answers the connect surface consults before routing or piping. */
|
|
2475
|
-
interface RcSelfHostSurface {
|
|
2476
|
-
/** The pipeline route serving the whole `/v1/code/sessions` family and the `/v1/sessions` compatibility list. */
|
|
2477
|
-
readonly route: FrontDoorRoute;
|
|
2478
|
-
/** The connect surface's local answers: which hosts it takes over as HTTP, and the requests it answers itself. */
|
|
2479
|
-
readonly local: {
|
|
2480
|
-
/** The hosts whose terminated sessions this surface needs parsed as HTTP (the control-plane host, normally byte-tapped). */
|
|
2481
|
-
readonly parsesHost: (host: string) => boolean;
|
|
2482
|
-
/** Serves one request locally; resolves false when the surface does not own the path, so routing or piping continues unchanged. */
|
|
2483
|
-
readonly serve: (host: string, request: IncomingMessage, response: ServerResponse) => Promise<boolean>;
|
|
2484
|
-
};
|
|
2485
|
-
/** Stops the service's timers and retires every open stream. The sessions themselves are unreachable the moment the door drops them. */
|
|
2486
|
-
readonly close: () => void;
|
|
2487
|
-
}
|
|
2488
|
-
/** Creates the self-hosted Remote Control service. One per door process; everything it holds dies with it. */
|
|
2489
|
-
declare function createRcSelfHostSurface(deps: RcSelfHostDeps): RcSelfHostSurface;
|
|
2490
|
-
|
|
2491
|
-
/** Where the door's own copy of the minted credential lives, under the door's state directory. */
|
|
2492
|
-
declare const RC_SELF_HOST_RECORD_DIR = "rc-selfhost";
|
|
2493
|
-
/** The door's copy of the minted credential: the record `rcSelfHost.ts` reads fresh on every authenticated call. */
|
|
2494
|
-
declare const RC_SELF_HOST_RECORD_FILE = "credential.json";
|
|
2495
|
-
/** Everything the minting needs, injected so it runs against an in-memory fake filesystem in unit tests. */
|
|
2496
|
-
interface RcSelfHostMintDeps {
|
|
2497
|
-
readonly fs: Pick<FarmFs, "readFileUtf8" | "writeFilePrivate" | "mkdirPrivate">;
|
|
2498
|
-
/** The agent-shim identities directory (the mint writes inside `<identitiesDir>/<identity>/`). */
|
|
2499
|
-
readonly identitiesDir: string;
|
|
2500
|
-
/** The door's state directory (the record is written under `<frontdoorDir>/rc-selfhost/`). */
|
|
2501
|
-
readonly frontdoorDir: string;
|
|
2502
|
-
readonly identity: string;
|
|
2503
|
-
/** Mints ids: a v4 UUID or better in production. */
|
|
2504
|
-
readonly newUuid: () => string;
|
|
2505
|
-
/** Mints token material: cryptographically random bytes in production. */
|
|
2506
|
-
readonly randomToken: () => string;
|
|
2507
|
-
/** Overwrite an existing credential that is not a previous mint of this door's. */
|
|
2508
|
-
readonly force: boolean;
|
|
2509
|
-
readonly now: () => number;
|
|
2510
|
-
}
|
|
2511
|
-
/** What the minting produced: names and shapes only, never a token. */
|
|
2512
|
-
interface RcSelfHostMintResult {
|
|
2513
|
-
readonly identity: string;
|
|
2514
|
-
readonly organizationUuid: string;
|
|
2515
|
-
readonly credentialsFile: string;
|
|
2516
|
-
readonly claudeJsonFile: string;
|
|
2517
|
-
readonly recordFile: string;
|
|
2518
|
-
/** Whether a previous mint of this door's was replaced. */
|
|
2519
|
-
readonly replaced: boolean;
|
|
2691
|
+
interface CredentialCachePort {
|
|
2692
|
+
readonly read: (store: CredentialCacheStore, owner: string) => CachedCredential | undefined;
|
|
2693
|
+
readonly write: (store: CredentialCacheStore, owner: string, entry: CachedCredential) => void;
|
|
2694
|
+
readonly remove: (store: CredentialCacheStore, owner: string) => void;
|
|
2520
2695
|
}
|
|
2521
|
-
/** Reads the door's previously minted record, or undefined when none exists (or what exists does not parse). */
|
|
2522
|
-
declare function readRcSelfHostRecord(fs: Pick<FarmFs, "readFileUtf8">, frontdoorDir: string): RcSelfHostCredentialRecord | undefined;
|
|
2523
2696
|
/**
|
|
2524
|
-
*
|
|
2697
|
+
* What the cache holds for one credential, without the token: whether there is an entry, how old it is, and whether it is still within the block's TTL. `expiresInMs` is absent for a block with no expiry.
|
|
2525
2698
|
*/
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
readonly
|
|
2699
|
+
type CachedCredentialState = {
|
|
2700
|
+
readonly store: CredentialCacheStore;
|
|
2701
|
+
readonly status: "empty";
|
|
2702
|
+
}
|
|
2703
|
+
/** The store cannot be read here (the keychain store configured on a platform without a Keychain): reported with its reason rather than failing the whole report. */
|
|
2704
|
+
| {
|
|
2705
|
+
readonly store: CredentialCacheStore;
|
|
2706
|
+
readonly status: "unreadable";
|
|
2533
2707
|
readonly reason: string;
|
|
2708
|
+
} | {
|
|
2709
|
+
readonly store: CredentialCacheStore;
|
|
2710
|
+
readonly status: "fresh" | "expired";
|
|
2711
|
+
readonly ageMs: number;
|
|
2712
|
+
readonly expiresInMs?: number;
|
|
2534
2713
|
};
|
|
2535
2714
|
|
|
2536
|
-
/**
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
}
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
readonly
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
readonly
|
|
2547
|
-
|
|
2548
|
-
readonly
|
|
2549
|
-
|
|
2550
|
-
readonly verifyListener: (port: number) => ListenerVerdict;
|
|
2551
|
-
/** Asks a running front-door supervisor to exit, without waiting for it to: the caller polls `isRunning`. Only ever called for a pid whose recorded listener has just authenticated as agent-shim's own. */
|
|
2552
|
-
readonly stopSupervisor: (pid: number) => void;
|
|
2715
|
+
/** What reading one `file` source found: nothing at that path, or its contents and permission bits. `mode` is undefined on a platform with no POSIX permission bits (Windows), where the looseness check cannot apply. */
|
|
2716
|
+
type SecretFileRead = {
|
|
2717
|
+
readonly found: false;
|
|
2718
|
+
} | {
|
|
2719
|
+
readonly found: true;
|
|
2720
|
+
readonly content: string;
|
|
2721
|
+
readonly mode: number | undefined;
|
|
2722
|
+
};
|
|
2723
|
+
/** The outcome of one credential command. `stderr` is empty for an interactive run, whose stderr goes to the terminal so a person sees any prompt. */
|
|
2724
|
+
interface CredentialCommandResult {
|
|
2725
|
+
readonly status: number | null;
|
|
2726
|
+
readonly stdout: string;
|
|
2727
|
+
readonly stderr: string;
|
|
2728
|
+
readonly timedOut: boolean;
|
|
2553
2729
|
}
|
|
2554
2730
|
/**
|
|
2555
|
-
*
|
|
2556
|
-
*
|
|
2557
|
-
* A live pid in state proves nothing about who holds the port it names: the door may have crashed and left the port to anyone, or the pid may have been reused by an unrelated process. So before anything is registered or returned, the provider listener is authenticated over TLS against agent-shim's CA. A listener that fails (wrong certificate, nothing answering, a bad answer) is treated as a stale or hostile owner: its pid is distrusted for the rest of this call and a replacement supervisor is spawned, which binds a free port when the sticky one is held and is then verified in turn. If a supervisor this call spawned also fails verification, the launch is refused naming the reason and the daemon log; no capability is written and no address is handed to the child.
|
|
2731
|
+
* Everything resolving a credential needs from the outside world, injected so the resolver (and every launcher test) runs without `op`, the Keychain, real secret files or a terminal. `src/realPorts.ts` wires the real one; tests wire a fake.
|
|
2558
2732
|
*/
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
readonly
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2733
|
+
interface CredentialPort {
|
|
2734
|
+
/** Reads a `file` source's path (absolute or `~`-rooted). */
|
|
2735
|
+
readonly readSecretFile: (filePath: string) => SecretFileRead;
|
|
2736
|
+
/** Runs a command source's argv directly (no shell) under a timeout, capturing stdout. An interactive run inherits the terminal's stdin and stderr so a person can answer a prompt. */
|
|
2737
|
+
readonly runCommand: (argv: readonly [string, ...string[]], options: {
|
|
2738
|
+
readonly timeoutMs: number;
|
|
2739
|
+
readonly interactive: boolean;
|
|
2740
|
+
}) => CredentialCommandResult;
|
|
2741
|
+
/** Whether a person can answer a prompt now: standard input is a terminal, or there is a desktop session to show a dialog in. */
|
|
2742
|
+
readonly personPresent: () => boolean;
|
|
2743
|
+
/** Where cached credentials live, used only for a credential block that asks for caching. Omit to resolve every launch from the sources. */
|
|
2744
|
+
readonly cache?: CredentialCacheEnv;
|
|
2745
|
+
}
|
|
2746
|
+
/** One source as `check`, `doctor` and every `--json` output report it: its kind plus the same non-secret identifying detail `describeSource` prints. */
|
|
2747
|
+
type CredentialSourceSummary = {
|
|
2748
|
+
readonly kind: "env";
|
|
2749
|
+
readonly variable: string;
|
|
2750
|
+
} | {
|
|
2751
|
+
readonly kind: "file";
|
|
2752
|
+
readonly path: string;
|
|
2753
|
+
} | {
|
|
2754
|
+
readonly kind: "command";
|
|
2755
|
+
readonly program: string;
|
|
2756
|
+
} | {
|
|
2757
|
+
readonly kind: "op";
|
|
2758
|
+
readonly reference: string;
|
|
2759
|
+
} | {
|
|
2760
|
+
readonly kind: "keychain";
|
|
2761
|
+
readonly service: string;
|
|
2762
|
+
readonly account?: string;
|
|
2763
|
+
} | {
|
|
2764
|
+
readonly kind: "literal";
|
|
2567
2765
|
};
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
readonly
|
|
2572
|
-
/**
|
|
2573
|
-
readonly
|
|
2766
|
+
/** A credential block as it is reported: its effective target and each source's summary, in order. */
|
|
2767
|
+
interface CredentialSummary {
|
|
2768
|
+
readonly target: CredentialTarget;
|
|
2769
|
+
readonly sources: readonly CredentialSourceSummary[];
|
|
2770
|
+
/** The block's cache setting when it asks for caching: how long a token is kept (absent for no expiry) and where. Carried as the config schema's own type, since the summary passes the parsed block's setting through unchanged. */
|
|
2771
|
+
readonly cache?: CredentialCache;
|
|
2574
2772
|
}
|
|
2575
|
-
/**
|
|
2576
|
-
interface
|
|
2577
|
-
readonly
|
|
2578
|
-
readonly
|
|
2579
|
-
readonly ownPid: number;
|
|
2773
|
+
/** What caching a credential needs beyond the block's own `cache` setting: the port holding entries, the platform that picks the default store, and the clock the TTL is measured on. */
|
|
2774
|
+
interface CredentialCacheEnv {
|
|
2775
|
+
readonly port: CredentialCachePort;
|
|
2776
|
+
readonly platform: NodeJS.Platform;
|
|
2580
2777
|
readonly now: () => number;
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
readonly
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2778
|
+
}
|
|
2779
|
+
|
|
2780
|
+
/** Where a pinned Claude Code version came from, strongest first: the launch's own flag, then the environment, then the cascade. */
|
|
2781
|
+
declare const CLAUDE_VERSION_SOURCES: readonly ["flag", "environment", "cascade"];
|
|
2782
|
+
type ClaudeVersionSource = (typeof CLAUDE_VERSION_SOURCES)[number];
|
|
2783
|
+
/** The pinned version a launch runs, and which of the three forms named it. */
|
|
2784
|
+
interface PinnedClaudeVersion {
|
|
2785
|
+
readonly version: string;
|
|
2786
|
+
readonly source: ClaudeVersionSource;
|
|
2787
|
+
}
|
|
2788
|
+
|
|
2789
|
+
/**
|
|
2790
|
+
* The environment variables that authenticate Claude Code directly from the process environment, ahead of any stored identity credential. If any of these is set, every identity would silently authenticate as the same key/token/backend while it's set — defeating the entire premise of separate identities. Order here is also lookup order: `detectAmbientCredential` reports the first one found.
|
|
2791
|
+
*/
|
|
2792
|
+
declare const AMBIENT_CREDENTIAL_VARS: readonly ["ANTHROPIC_API_KEY", "ANTHROPIC_AUTH_TOKEN", "CLAUDE_CODE_OAUTH_TOKEN", "CLAUDE_CODE_USE_BEDROCK", "CLAUDE_CODE_USE_VERTEX", "CLAUDE_CODE_USE_FOUNDRY"];
|
|
2793
|
+
type AmbientCredentialVar = (typeof AMBIENT_CREDENTIAL_VARS)[number];
|
|
2794
|
+
/** Which guarded variable was found set, and to what. */
|
|
2795
|
+
interface AmbientCredentialDetection {
|
|
2796
|
+
readonly variable: AmbientCredentialVar;
|
|
2797
|
+
}
|
|
2798
|
+
/** A credential this launch itself exports to the child: the variable it lands in and its value. */
|
|
2799
|
+
interface InjectedCredential {
|
|
2800
|
+
readonly variable: CredentialTargetVar;
|
|
2801
|
+
readonly token: string;
|
|
2802
|
+
}
|
|
2803
|
+
/**
|
|
2804
|
+
* Detects whether any of `AMBIENT_CREDENTIAL_VARS` is set to a non-empty value in `env`, returning the first one found in declared order, or undefined when none are set.
|
|
2805
|
+
*
|
|
2806
|
+
* An empty string counts as unset, not set — confirmed load-bearing: one of Joe's real wrapper scripts (`o`, running Claude Code against OpenRouter) does `export ANTHROPIC_API_KEY=""` specifically to *clear* it so `ANTHROPIC_AUTH_TOKEN` takes effect instead, and this must never trip the guard.
|
|
2807
|
+
*
|
|
2808
|
+
* `injected`, when given, is the credential this launch exports for its own identity. Its variable holding exactly that value is not ambient: it is what a agent-shim launch of the same identity left in the environment of the session this one starts from (a `claude @work` run inside a `claude @work` session). The same variable holding any other value still counts.
|
|
2809
|
+
*/
|
|
2810
|
+
declare function detectAmbientCredential(env: Readonly<Record<string, string | undefined>>, injected?: InjectedCredential): AmbientCredentialDetection | undefined;
|
|
2811
|
+
/**
|
|
2812
|
+
* Builds the exact refusal message: which variable was found, why it matters, and the two ways to opt in (a one-off env var, or a persistent per-identity setting). Mirrors the message documented in the project's README. `identityName` is included in the persistent-opt-in command when known; when no identity has been resolved yet (e.g. the `CLAUDE_CONFIG_DIR`-already-set escape hatch, or no identity resolved at all), a generic `<name>` placeholder is used instead, matching the README's own generic wording.
|
|
2813
|
+
*/
|
|
2814
|
+
declare function formatAmbientCredentialGuardMessage(variable: AmbientCredentialVar, identityName?: string): string;
|
|
2815
|
+
/** Inputs to the ambient-credential guard evaluation. */
|
|
2816
|
+
interface EvaluateAmbientCredentialGuardParams {
|
|
2817
|
+
readonly env: Readonly<Record<string, string | undefined>>;
|
|
2818
|
+
/** The active identity's own `allowAmbientCredential` setting from its `identity.json`, or false when no identity is known. */
|
|
2819
|
+
readonly allowAmbientCredential: boolean;
|
|
2820
|
+
/** True when `AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL=1` is set for this one invocation. */
|
|
2821
|
+
readonly allowAmbientCredentialOverride: boolean;
|
|
2822
|
+
/** The active identity's name, for the message's persistent-opt-in command. Undefined when no identity is known. */
|
|
2823
|
+
readonly identityName?: string;
|
|
2593
2824
|
/**
|
|
2594
|
-
*
|
|
2825
|
+
* True when this launch routes through an API provider. The guard inspects the PARENT environment, before `buildEnv` runs; a provider launch has its `ANTHROPIC_AUTH_TOKEN` injected and its `ANTHROPIC_API_KEY` cleared by `buildEnv` itself, so an ambient credential in the parent environment never reaches the child and there is nothing left for this guard to protect against. Everything else about the guard (including `IdentitySchema.allowAmbientCredential`) is unchanged by this flag.
|
|
2595
2826
|
*/
|
|
2596
|
-
readonly
|
|
2597
|
-
|
|
2827
|
+
readonly providerSelected?: boolean;
|
|
2828
|
+
/** The launching identity's own credential, when its credential block resolved: see `detectAmbientCredential`. */
|
|
2829
|
+
readonly injectedCredential?: InjectedCredential;
|
|
2830
|
+
}
|
|
2831
|
+
/** The result of one guard evaluation: either launch may proceed, or it must be refused with an explanatory message. */
|
|
2832
|
+
type AmbientCredentialGuardResult = {
|
|
2833
|
+
readonly ok: true;
|
|
2834
|
+
} | {
|
|
2835
|
+
readonly ok: false;
|
|
2836
|
+
readonly variable: AmbientCredentialVar;
|
|
2837
|
+
readonly message: string;
|
|
2838
|
+
};
|
|
2839
|
+
/**
|
|
2840
|
+
* Evaluates the ambient-credential guard: refuses unless no guarded variable is set, or the active identity opted in (`allowAmbientCredential: true`), or this one invocation opted in (`AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL=1`), or a provider takes over the child's credential (see `providerSelected`).
|
|
2841
|
+
*
|
|
2842
|
+
* This guard is about credential isolation, not identity/config-dir selection — it must still run even when the `CLAUDE_CONFIG_DIR`-already-set escape hatch applies (callers pass `allowAmbientCredential: false` and no `identityName` in that case, since there is no active identity to consult).
|
|
2843
|
+
*/
|
|
2844
|
+
declare function evaluateAmbientCredentialGuard(params: EvaluateAmbientCredentialGuardParams): AmbientCredentialGuardResult;
|
|
2845
|
+
|
|
2846
|
+
/** Which precedence rule produced an identity decision. */
|
|
2847
|
+
declare const IDENTITY_DECISION_SOURCES: readonly ["config-dir-escape-hatch", "argv", "env", "directory-pin", "active-identity-file", "none"];
|
|
2848
|
+
type IdentityDecisionSource = (typeof IDENTITY_DECISION_SOURCES)[number];
|
|
2849
|
+
/** Which precedence rule produced a configuration-profile decision. */
|
|
2850
|
+
declare const CONFIG_PROFILE_DECISION_SOURCES: readonly ["cli-flag", "env", "directory-rule", "identity-default", "global-default", "none"];
|
|
2851
|
+
type ConfigProfileDecisionSource = (typeof CONFIG_PROFILE_DECISION_SOURCES)[number];
|
|
2852
|
+
|
|
2853
|
+
/** What `pool pick` reports: the ranking a launch from `directory` would act on right now. */
|
|
2854
|
+
declare const PoolPickReportSchema: z.ZodObject<{
|
|
2855
|
+
pool: z.ZodString;
|
|
2856
|
+
directory: z.ZodString;
|
|
2857
|
+
pick: z.ZodOptional<z.ZodString>;
|
|
2858
|
+
candidates: z.ZodArray<z.ZodObject<{
|
|
2859
|
+
identity: z.ZodString;
|
|
2860
|
+
class: z.ZodEnum<{
|
|
2861
|
+
unknown: "unknown";
|
|
2862
|
+
scored: "scored";
|
|
2863
|
+
"pay-per-use": "pay-per-use";
|
|
2864
|
+
ineligible: "ineligible";
|
|
2865
|
+
}>;
|
|
2866
|
+
score: z.ZodOptional<z.ZodNumber>;
|
|
2867
|
+
feasible: z.ZodBoolean;
|
|
2868
|
+
blockedUntil: z.ZodOptional<z.ZodISODateTime>;
|
|
2869
|
+
plan: z.ZodUnion<readonly [z.ZodObject<{
|
|
2870
|
+
kind: z.ZodLiteral<"subscription">;
|
|
2871
|
+
capacity: z.ZodNumber;
|
|
2872
|
+
recognised: z.ZodBoolean;
|
|
2873
|
+
tier: z.ZodOptional<z.ZodString>;
|
|
2874
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2875
|
+
kind: z.ZodLiteral<"pay-per-use">;
|
|
2876
|
+
tier: z.ZodOptional<z.ZodString>;
|
|
2877
|
+
}, z.core.$strict>]>;
|
|
2878
|
+
reasons: z.ZodArray<z.ZodString>;
|
|
2879
|
+
}, z.core.$strict>>;
|
|
2880
|
+
missing: z.ZodArray<z.ZodString>;
|
|
2881
|
+
earliestReturn: z.ZodOptional<z.ZodObject<{
|
|
2882
|
+
identity: z.ZodString;
|
|
2883
|
+
at: z.ZodISODateTime;
|
|
2884
|
+
}, z.core.$strict>>;
|
|
2885
|
+
stickyProblem: z.ZodOptional<z.ZodString>;
|
|
2886
|
+
}, z.core.$strict>;
|
|
2887
|
+
type PoolPickReport = z.infer<typeof PoolPickReportSchema>;
|
|
2888
|
+
|
|
2889
|
+
/**
|
|
2890
|
+
* Forward-only encoding of a real working directory into the single directory name Claude Code gives it under `~/.claude/projects/`.
|
|
2891
|
+
*
|
|
2892
|
+
* The encoding collapses the *entire* non-alphanumeric character class to `-`, not just the path separator: `.`, `_`, ` `, `@`, and `/` all become `-`, while letters and digits pass through with their case preserved. This was confirmed against a real installation's project directories, not assumed from the one `/`-becomes-`-` sample the README quotes.
|
|
2893
|
+
*
|
|
2894
|
+
* The encoding is therefore many-to-one: `~/work/clients/acme`, `~/work/clients-acme`, and `~/work-clients/acme` all produce the identical name. That makes it impossible to invert, so this module never tries: there is no decode function here, and `projects.test.ts` asserts the module's export list to keep it that way. Only the forward direction — real path to encoded name — is ever computed, and `detectEncodingAmbiguity` reports when a pattern's encoded form could plausibly correspond to more than one real path rather than resolving it silently.
|
|
2895
|
+
*/
|
|
2896
|
+
|
|
2897
|
+
/** Why a pattern's encoded form might not identify the real path its author had in mind. */
|
|
2898
|
+
declare const ENCODING_AMBIGUITY_REASONS: readonly ["lossy-characters", "collides-with-sibling-pattern"];
|
|
2899
|
+
type EncodingAmbiguityReason = (typeof ENCODING_AMBIGUITY_REASONS)[number];
|
|
2900
|
+
/** One reported ambiguity in a `history/projects/` pattern. */
|
|
2901
|
+
interface EncodingAmbiguity {
|
|
2902
|
+
readonly fragment: string;
|
|
2903
|
+
readonly encoded: string;
|
|
2904
|
+
readonly reason: EncodingAmbiguityReason;
|
|
2905
|
+
readonly detail: string;
|
|
2906
|
+
}
|
|
2907
|
+
|
|
2908
|
+
/** The result of looking up the macOS Keychain service name Claude Code is actually using for one identity's farm. */
|
|
2909
|
+
interface KeychainLookupResult {
|
|
2910
|
+
readonly checked: true;
|
|
2911
|
+
readonly found: boolean;
|
|
2912
|
+
readonly serviceName?: string;
|
|
2913
|
+
readonly note: string;
|
|
2914
|
+
}
|
|
2915
|
+
/** One file's reported settings exposure: names and counts only, never the underlying values. */
|
|
2916
|
+
interface SettingsExposureReport {
|
|
2917
|
+
readonly file: string;
|
|
2918
|
+
readonly envKeyNames: readonly string[];
|
|
2919
|
+
readonly hookEventNames: readonly string[];
|
|
2920
|
+
readonly hookCommandCount: number;
|
|
2921
|
+
}
|
|
2922
|
+
/** The provider the cascade selects for this directory, as the wiring layer loaded it: its definition, or why it could not be used (no such provider, an invalid or old-format file). */
|
|
2923
|
+
type CheckProviderInput = {
|
|
2924
|
+
readonly name: string;
|
|
2925
|
+
readonly definition: Provider;
|
|
2926
|
+
readonly problem?: never;
|
|
2927
|
+
} | {
|
|
2928
|
+
readonly name: string;
|
|
2929
|
+
readonly definition?: never;
|
|
2930
|
+
readonly problem: string;
|
|
2931
|
+
};
|
|
2932
|
+
/**
|
|
2933
|
+
* Which credential a launch here would use, by source kind and target only: a selected provider's credential block always wins; otherwise the identity's own credential block; otherwise the login stored in the identity's directory.
|
|
2934
|
+
*/
|
|
2935
|
+
interface CredentialReport {
|
|
2936
|
+
readonly applies: (typeof CHECK_CREDENTIAL_APPLIES)[number];
|
|
2937
|
+
/** The selected provider's usable block (with what its cache holds), or why it could not be used; the two never appear together, exactly as `CheckProviderInput` states it. */
|
|
2938
|
+
readonly provider?: {
|
|
2939
|
+
readonly name: string;
|
|
2940
|
+
readonly credential: CredentialSummary;
|
|
2941
|
+
readonly cached?: CachedCredentialState;
|
|
2942
|
+
readonly problem?: never;
|
|
2943
|
+
} | {
|
|
2944
|
+
readonly name: string;
|
|
2945
|
+
readonly problem: string;
|
|
2946
|
+
readonly credential?: never;
|
|
2947
|
+
readonly cached?: never;
|
|
2948
|
+
};
|
|
2949
|
+
readonly identity?: CredentialSummary;
|
|
2950
|
+
/** What the identity's own credential cache holds, when its block caches and the cache could be read. */
|
|
2951
|
+
readonly identityCached?: CachedCredentialState;
|
|
2952
|
+
}
|
|
2953
|
+
/** Inputs to `runCheck` — everything already loaded/injected, exactly like the resolver core and the launcher: nothing in this function touches a real filesystem, git repository, clock, or environment itself. */
|
|
2954
|
+
interface RunCheckParams {
|
|
2955
|
+
readonly cwd: string;
|
|
2956
|
+
readonly home: string;
|
|
2957
|
+
readonly claudeHome: string;
|
|
2958
|
+
readonly env: Readonly<Record<string, string | undefined>>;
|
|
2959
|
+
readonly branch?: string;
|
|
2960
|
+
readonly branchDetached?: boolean;
|
|
2961
|
+
readonly nowMs: number;
|
|
2962
|
+
/** Used only to build the fact manifest by reading the canonical `~/.claude` tree — `runCheck` never mutates the farm and never spawns anything. */
|
|
2963
|
+
readonly farmFs: FarmFs;
|
|
2964
|
+
readonly cascade: CascadeInput;
|
|
2965
|
+
readonly classification: {
|
|
2966
|
+
readonly defaults: CategoryClassification;
|
|
2967
|
+
readonly overlay?: CategoryClassificationOverlay;
|
|
2968
|
+
};
|
|
2969
|
+
readonly identityName?: string;
|
|
2970
|
+
readonly identitySource: IdentityDecisionSource;
|
|
2971
|
+
/** The pool the launch selected and how it ranks right now, when it named a pool instead of an identity; `identityName` is then the member it would pick. */
|
|
2972
|
+
readonly poolPick?: PoolPickReport;
|
|
2973
|
+
readonly configProfileName?: string;
|
|
2974
|
+
readonly configProfileSource: ConfigProfileDecisionSource;
|
|
2975
|
+
/** The resolved identity's own `identity.json`, when one was found. */
|
|
2976
|
+
readonly identity?: Identity;
|
|
2977
|
+
/** Raw `settings.json`/`settings.local.json` contents, keyed by filename, undefined when a file does not exist. */
|
|
2978
|
+
readonly settingsFiles: Readonly<Record<string, string | undefined>>;
|
|
2979
|
+
/** Runs `security find-generic-password` for the Keychain diagnostic. Omit to skip that diagnostic entirely (e.g. off macOS, or when no identity/farm root is known). */
|
|
2980
|
+
readonly run?: RunPort;
|
|
2981
|
+
/** The identity's own farm root — `security`'s lookup account. Required alongside `run` for the Keychain diagnostic to run at all. */
|
|
2982
|
+
readonly farmRoot?: string;
|
|
2983
|
+
/** `process.platform` in real use; the Keychain diagnostic only ever runs when this is `"darwin"`. */
|
|
2984
|
+
readonly platform: string;
|
|
2985
|
+
/** The provider a launch here would route through (`launch.provider` in the cascade), when one is selected. */
|
|
2986
|
+
readonly provider?: CheckProviderInput;
|
|
2987
|
+
/** The Claude Code versions installed here, oldest first. Omit to leave the Claude Code version out of the report; with it, `check` says which version a launch here runs and whether a pin is installed. */
|
|
2988
|
+
readonly installedClaudeVersions?: readonly string[];
|
|
2989
|
+
/** Where cached credentials live. Omit to skip reporting a credential cache's age; with it, a block that caches reports whether it holds an entry, how old it is and whether it has expired, never the token. */
|
|
2990
|
+
readonly credentialCache?: CredentialCacheEnv;
|
|
2991
|
+
}
|
|
2992
|
+
/** Everything `agent-shim check` reports about one directory/identity, without touching the farm or spawning anything. */
|
|
2993
|
+
interface CheckReport {
|
|
2994
|
+
readonly identityName?: string;
|
|
2995
|
+
readonly identitySource: IdentityDecisionSource;
|
|
2996
|
+
readonly poolPick?: PoolPickReport;
|
|
2997
|
+
readonly configProfileName?: string;
|
|
2998
|
+
readonly configProfileSource: ConfigProfileDecisionSource;
|
|
2999
|
+
readonly resolved: ResolvedState;
|
|
3000
|
+
readonly decisionLines: readonly string[];
|
|
3001
|
+
readonly projectEncodingAmbiguities: readonly EncodingAmbiguity[];
|
|
3002
|
+
readonly ambientCredential: AmbientCredentialGuardResult;
|
|
3003
|
+
readonly keychain?: KeychainLookupResult;
|
|
3004
|
+
readonly settingsExposure: readonly SettingsExposureReport[];
|
|
3005
|
+
readonly credential: CredentialReport;
|
|
3006
|
+
/** The Claude Code version a launch here would run, when the installed versions were given. */
|
|
3007
|
+
readonly claudeVersion?: ClaudeVersionReport;
|
|
3008
|
+
}
|
|
3009
|
+
/** Which Claude Code version a launch would run: the pin and where it comes from, with whether it is installed, or the highest installed version when nothing pins one. */
|
|
3010
|
+
interface ClaudeVersionReport {
|
|
3011
|
+
readonly pinned?: PinnedClaudeVersion & {
|
|
3012
|
+
readonly installed: boolean;
|
|
3013
|
+
};
|
|
3014
|
+
readonly highestInstalled?: string;
|
|
3015
|
+
readonly installed: readonly string[];
|
|
3016
|
+
}
|
|
3017
|
+
/**
|
|
3018
|
+
* Resolves the full cascade for one directory/identity and reports everything `agent-shim check` documents: every entry's resolved state and which layer/condition decided it, any ambiguous `history/projects/` encoding in scope, and the three always-on diagnostics (ambient-credential exposure, macOS Keychain service name, settings-secrets exposure).
|
|
3019
|
+
*
|
|
3020
|
+
* Deliberately reuses the same cascade machinery a real launch uses — `resolveDecisions` and `buildEntryFacts` — rather than reimplementing any part of resolution. The one thing this function never does that a launch does is touch the farm or spawn anything: it only reads the canonical `~/.claude` tree to build the fact manifest resolution needs, and every other input (cascade, classification, settings file contents, the Keychain lookup) is handed in already loaded.
|
|
3021
|
+
*/
|
|
3022
|
+
declare function runCheck(params: RunCheckParams): CheckReport;
|
|
3023
|
+
/** Renders a full `CheckReport` as plain text lines, in the order `agent-shim check` prints them. */
|
|
3024
|
+
declare function formatCheckReport(report: CheckReport): string[];
|
|
3025
|
+
/**
|
|
3026
|
+
* The `check --json` form of a report: every field the text form prints, as plain data (no `Map`s, no compiled matchers), so a script can read the same verdicts a person would.
|
|
3027
|
+
*/
|
|
3028
|
+
declare function checkReportToJson(report: CheckReport): CheckReportJson;
|
|
3029
|
+
/**
|
|
3030
|
+
* Whether a report carries anything `check --strict` fails on: a resolver diagnostic of warning or error severity, an ambiguous `history/projects/` encoding, an ambient credential a launch would refuse, or a selected provider a launch could not use. Informational diagnostics and the settings-exposure advisory (names and counts only, for a person to review) never fail it.
|
|
3031
|
+
*/
|
|
3032
|
+
declare function checkReportHasWarnings(report: CheckReport): boolean;
|
|
3033
|
+
/** What `collectCheckReport` needs from its caller. */
|
|
3034
|
+
interface CollectCheckReportParams {
|
|
3035
|
+
readonly paths: LayoutPaths;
|
|
3036
|
+
/** The directory a launch would run in; resolved against the working directory by the caller. */
|
|
3037
|
+
readonly cwd: string;
|
|
3038
|
+
/** The identity to check, as `--identity` names it; absent means the identity a launch there would resolve. */
|
|
3039
|
+
readonly identity?: string;
|
|
3040
|
+
readonly env: NodeJS.ProcessEnv;
|
|
3041
|
+
}
|
|
3042
|
+
/**
|
|
3043
|
+
* Resolves what a launch in `params.cwd` would share or hide, and why, against this machine: the edge adapter that reads the real filesystem, clock, git and keychain, resolves the identity, configuration profile and cascade exactly as a launch does, and hands the facts to the pure `runCheck`. Never touches the farm or spawns claude.
|
|
3044
|
+
*/
|
|
3045
|
+
declare function collectCheckReport(params: CollectCheckReportParams): CheckReport;
|
|
3046
|
+
|
|
3047
|
+
declare const ClaudeShimStateSchema: z.ZodObject<{
|
|
3048
|
+
targetPath: z.ZodString;
|
|
3049
|
+
method: z.ZodEnum<{
|
|
3050
|
+
hardlink: "hardlink";
|
|
3051
|
+
copy: "copy";
|
|
3052
|
+
}>;
|
|
3053
|
+
installedAtMs: z.ZodNumber;
|
|
3054
|
+
}, z.core.$strict>;
|
|
3055
|
+
type ClaudeShimState = z.infer<typeof ClaudeShimStateSchema>;
|
|
3056
|
+
type PathShadowStatus = {
|
|
3057
|
+
readonly status: "ok";
|
|
3058
|
+
} | {
|
|
3059
|
+
readonly status: "not-on-path";
|
|
3060
|
+
} | {
|
|
3061
|
+
readonly status: "shadowed";
|
|
3062
|
+
readonly by: string;
|
|
3063
|
+
};
|
|
3064
|
+
|
|
3065
|
+
/** The result of a successful discovery. */
|
|
3066
|
+
interface DiscoveredClaudeBinary {
|
|
3067
|
+
/** Full path to the discovered `claude` executable. */
|
|
3068
|
+
path: string;
|
|
3069
|
+
/** Which strategy found it. */
|
|
3070
|
+
source: "versions-dir" | "path-fallback";
|
|
3071
|
+
/** The version string, when discovered via the versions directory. */
|
|
3072
|
+
version?: string;
|
|
3073
|
+
}
|
|
3074
|
+
/** What a launch asks binary discovery for: nothing (the highest installed version) or an exact version. */
|
|
3075
|
+
interface ClaudeBinaryRequest {
|
|
3076
|
+
readonly version?: string;
|
|
3077
|
+
}
|
|
3078
|
+
/** Discovers the real `claude` binary to spawn, for the version a launch asked for. Injected into the launcher so it never reads the filesystem or PATH itself. */
|
|
3079
|
+
type ClaudeBinaryResolver = (request?: Readonly<ClaudeBinaryRequest>) => DiscoveredClaudeBinary;
|
|
3080
|
+
|
|
3081
|
+
declare const DOCTOR_SEVERITIES: readonly ["pass", "warn", "fail"];
|
|
3082
|
+
type DoctorSeverity = (typeof DOCTOR_SEVERITIES)[number];
|
|
3083
|
+
declare const DOCTOR_SECTIONS: readonly ["ambient-credential", "binary-discovery", "claude-shim", "path-resolution", "legacy-name", "config-profile", "identity", "pool", "provider", "keychain", "directory-rules", "global-config", "categories-local", "active-identity", "headroom"];
|
|
3084
|
+
type DoctorSection = (typeof DOCTOR_SECTIONS)[number];
|
|
3085
|
+
/** One line of `agent-shim doctor`'s report. `subject` names the identity/profile/rule the finding is about, when the section has more than one of those. */
|
|
3086
|
+
interface DoctorFinding {
|
|
3087
|
+
readonly section: DoctorSection;
|
|
3088
|
+
readonly subject?: string;
|
|
3089
|
+
readonly severity: DoctorSeverity;
|
|
3090
|
+
readonly message: string;
|
|
3091
|
+
}
|
|
3092
|
+
/** The full result of `runDoctor`. `ok` is false iff any finding is a `fail` — a `warn` never fails the report on its own. */
|
|
3093
|
+
interface DoctorReport {
|
|
3094
|
+
readonly findings: readonly DoctorFinding[];
|
|
3095
|
+
readonly ok: boolean;
|
|
3096
|
+
}
|
|
3097
|
+
/** One identity's raw `identity.json`, unparsed — `runDoctor` does its own JSON.parse/schema validation so one malformed file never aborts the rest of the report. */
|
|
3098
|
+
interface DoctorIdentityInput {
|
|
3099
|
+
readonly name: string;
|
|
3100
|
+
readonly path: string;
|
|
3101
|
+
readonly raw: string | undefined;
|
|
3102
|
+
/** The identity's own farm root (`identitiesDir/<name>`) — the account name the Keychain lookup uses. */
|
|
3103
|
+
readonly farmRoot: string;
|
|
3104
|
+
}
|
|
3105
|
+
/** One configuration profile's raw `<name>.json`, unparsed. */
|
|
3106
|
+
interface DoctorConfigProfileInput {
|
|
3107
|
+
readonly name: string;
|
|
3108
|
+
readonly path: string;
|
|
3109
|
+
readonly raw: string | undefined;
|
|
2598
3110
|
}
|
|
2599
|
-
/**
|
|
2600
|
-
interface
|
|
2601
|
-
|
|
2602
|
-
readonly
|
|
3111
|
+
/** One provider's raw `<name>.json`, unparsed. */
|
|
3112
|
+
interface DoctorProviderInput {
|
|
3113
|
+
readonly name: string;
|
|
3114
|
+
readonly path: string;
|
|
3115
|
+
readonly raw: string | undefined;
|
|
3116
|
+
}
|
|
3117
|
+
/** A single optional top-level file `runDoctor` validates against a schema when present — absent is a legitimate, unconfigured state, not a failure. */
|
|
3118
|
+
interface DoctorFileInput {
|
|
3119
|
+
readonly path: string;
|
|
3120
|
+
readonly raw: string | undefined;
|
|
2603
3121
|
}
|
|
3122
|
+
/** The outcome of resolving the real Claude Code binary, pre-resolved by the wiring layer since `discoverClaudeBinary` is not itself a parse-shaped pure operation and already has its own dedicated test coverage. */
|
|
3123
|
+
type DoctorBinaryDiscovery = {
|
|
3124
|
+
readonly ok: true;
|
|
3125
|
+
readonly binary: DiscoveredClaudeBinary;
|
|
3126
|
+
} | {
|
|
3127
|
+
readonly ok: false;
|
|
3128
|
+
readonly message: string;
|
|
3129
|
+
};
|
|
2604
3130
|
/**
|
|
2605
|
-
*
|
|
3131
|
+
* Where a bare command name resolves for the two names this tool owns.
|
|
2606
3132
|
*
|
|
2607
|
-
*
|
|
3133
|
+
* `ownExecutablePath` is this process's own PATH-visible location (`realOwnExecutablePath()`); `agentShim` is `findPathShadow`'s verdict for a bare `agent-shim` against the directory that executable lives in. `claude` is only populated when a shim is actually enabled — without one, a `claude` on PATH is Claude Code's own binary, which is not a shadow of anything.
|
|
2608
3134
|
*/
|
|
2609
|
-
|
|
3135
|
+
interface DoctorPathResolution {
|
|
3136
|
+
readonly ownExecutablePath: string;
|
|
3137
|
+
readonly agentShim: PathShadowStatus;
|
|
3138
|
+
readonly claude?: PathShadowStatus;
|
|
3139
|
+
}
|
|
3140
|
+
/** Everything `runDoctor` needs, all of it already loaded/injected — nothing in `runDoctor` itself reads a file, shells out, or touches the farm. */
|
|
3141
|
+
interface RunDoctorParams {
|
|
3142
|
+
readonly env: Readonly<Record<string, string | undefined>>;
|
|
3143
|
+
/** The Claude Code versions installed here, oldest first. Omit to skip checking that a pinned version (`launch.claudeVersion`) is installed; with it, a profile, directory rule or global config pinning a version that is not installed is a warning. */
|
|
3144
|
+
readonly installedClaudeVersions?: readonly string[];
|
|
3145
|
+
/** Where cached credentials live. Omit to leave a credential cache's age out of the identity and provider findings; with it, a block that caches reports whether it holds an entry, how old it is and whether it has expired, never the token. */
|
|
3146
|
+
readonly credentialCache?: CredentialCacheEnv;
|
|
3147
|
+
readonly identities: readonly DoctorIdentityInput[];
|
|
3148
|
+
readonly configProfiles: readonly DoctorConfigProfileInput[];
|
|
3149
|
+
readonly providers: readonly DoctorProviderInput[];
|
|
3150
|
+
readonly directoryRules: DoctorFileInput;
|
|
3151
|
+
readonly globalConfig: DoctorFileInput;
|
|
3152
|
+
readonly categoriesLocal: DoctorFileInput;
|
|
3153
|
+
readonly activeIdentity: DoctorFileInput;
|
|
3154
|
+
readonly binaryDiscovery: DoctorBinaryDiscovery;
|
|
3155
|
+
/** Whether `agent-shim shim enable` has been run, and whether its recorded target still exists on disk — pre-resolved by the wiring layer, since checking a file's existence is real I/O, not a parse-shaped pure operation. */
|
|
3156
|
+
readonly claudeShim: {
|
|
3157
|
+
readonly state: ClaudeShimState | undefined;
|
|
3158
|
+
readonly targetExists: boolean;
|
|
3159
|
+
};
|
|
3160
|
+
/** Which executables a bare `agent-shim` (and, when the shim is enabled, a bare `claude`) would actually run — pre-resolved by the wiring layer, since scanning PATH is real I/O. */
|
|
3161
|
+
readonly pathResolution: DoctorPathResolution;
|
|
3162
|
+
/** The resolved state root (`paths.root`), whose directory name says whether this installation still lives under the former `.claude-use` name. */
|
|
3163
|
+
readonly rootPath: string;
|
|
3164
|
+
/** Runs `security find-generic-password` for the per-identity Keychain check. Omit to skip that check entirely (e.g. off macOS). */
|
|
3165
|
+
readonly run?: RunPort;
|
|
3166
|
+
/** `process.platform` in real use; the Keychain check only ever runs when this is `"darwin"`. */
|
|
3167
|
+
readonly platform: string;
|
|
3168
|
+
/** The headroom daemon's state.json plus a zombie-aware liveness predicate for the pids it names (a defunct daemon serves nothing but still answers signal 0). Omit the raw text when the daemon has never run; that is a pass, not a failure. */
|
|
3169
|
+
readonly headroom: {
|
|
3170
|
+
readonly state: DoctorFileInput;
|
|
3171
|
+
readonly isRunning: (pid: number) => boolean;
|
|
3172
|
+
};
|
|
3173
|
+
}
|
|
3174
|
+
/**
|
|
3175
|
+
* Audits the whole `~/.agent-shim` config graph for internal consistency: every identity, every configuration profile's own `extends` chain, every provider, `directory-rules.json`, `config.json`, `categories.local.json`, `active-identity`, plus real Claude Code binary discoverability and ambient-credential exposure.
|
|
3176
|
+
*
|
|
3177
|
+
* Deliberately identity/directory-agnostic, unlike `runCheck` — there is no single cascade to resolve `doctor` against, so it never touches settings-exposure (which only means anything relative to one resolved cascade).
|
|
3178
|
+
*
|
|
3179
|
+
* Every check aggregates rather than throws: a malformed file becomes one `fail` finding for that file, not an aborted report. This is the one place in the codebase that deliberately breaks the "throw a validation error and let it propagate" convention every other command relies on — `doctor`'s whole purpose is to survive a broken file and keep auditing everything else.
|
|
3180
|
+
*/
|
|
3181
|
+
declare function runDoctor(params: RunDoctorParams): DoctorReport;
|
|
3182
|
+
/** Renders a full `DoctorReport` as plain text lines, one section header at a time, in the order `agent-shim doctor` prints them. */
|
|
3183
|
+
declare function formatDoctorReport(report: DoctorReport): string[];
|
|
3184
|
+
/** What `collectDoctorReport` needs from its caller. */
|
|
3185
|
+
interface CollectDoctorReportParams {
|
|
3186
|
+
readonly paths: LayoutPaths;
|
|
3187
|
+
readonly env: NodeJS.ProcessEnv;
|
|
3188
|
+
}
|
|
3189
|
+
/**
|
|
3190
|
+
* Audits the whole state root against this machine: the edge adapter that enumerates every identity, configuration profile and provider on disk, reads every top-level config file as raw text (never pre-parsing, so one malformed file cannot abort the report), discovers the real Claude Code binary and resolves where a bare command name runs from, and hands the facts to the pure `runDoctor`.
|
|
3191
|
+
*/
|
|
3192
|
+
declare function collectDoctorReport(params: CollectDoctorReportParams): DoctorReport;
|
|
2610
3193
|
|
|
2611
3194
|
/** One routed request, appended to the usage log when its response has finished. */
|
|
2612
3195
|
declare const UsageRecordSchema: z.ZodObject<{
|
|
@@ -2752,1093 +3335,2064 @@ declare const UsageSnapshotSchema: z.ZodObject<{
|
|
|
2752
3335
|
}, z.core.$strict>>;
|
|
2753
3336
|
}, z.core.$strict>>;
|
|
2754
3337
|
}, z.core.$strict>;
|
|
2755
|
-
type UsageSnapshot = z.infer<typeof UsageSnapshotSchema>;
|
|
3338
|
+
type UsageSnapshot = z.infer<typeof UsageSnapshotSchema>;
|
|
3339
|
+
|
|
3340
|
+
/** The record held in one front-door session-registry file: the launcher's pid plus the per-launch capability token its child presents on every request. */
|
|
3341
|
+
declare const FrontDoorSessionSchema: z.ZodObject<{
|
|
3342
|
+
pid: z.ZodNumber;
|
|
3343
|
+
startedAt: z.ZodNumber;
|
|
3344
|
+
token: z.ZodString;
|
|
3345
|
+
}, z.core.$strict>;
|
|
3346
|
+
type FrontDoorSession = z.infer<typeof FrontDoorSessionSchema>;
|
|
3347
|
+
/**
|
|
3348
|
+
* The front-door supervisor's state.json under `<home>/frontdoor/`. Every field is optional because the file exists in stages, exactly like headroom's and the old codex daemon's: a fresh supervisor writes its own pid before the listener is up, and a shut-down front door leaves only the sticky `lastPort` and any `lastError` worth surfacing.
|
|
3349
|
+
*/
|
|
3350
|
+
declare const FrontDoorStateSchema: z.ZodObject<{
|
|
3351
|
+
protocol: z.ZodOptional<z.ZodNumber>;
|
|
3352
|
+
supervisorPid: z.ZodOptional<z.ZodNumber>;
|
|
3353
|
+
port: z.ZodOptional<z.ZodNumber>;
|
|
3354
|
+
lastPort: z.ZodOptional<z.ZodNumber>;
|
|
3355
|
+
connectPort: z.ZodOptional<z.ZodNumber>;
|
|
3356
|
+
lastConnectPort: z.ZodOptional<z.ZodNumber>;
|
|
3357
|
+
directPort: z.ZodOptional<z.ZodNumber>;
|
|
3358
|
+
lastDirectPort: z.ZodOptional<z.ZodNumber>;
|
|
3359
|
+
lastError: z.ZodOptional<z.ZodString>;
|
|
3360
|
+
}, z.core.$strict>;
|
|
3361
|
+
type FrontDoorState = z.infer<typeof FrontDoorStateSchema>;
|
|
3362
|
+
/** A registered launch as status and the idle decision see it: the pid and start time, never the token, so nothing that prints or serialises a session can leak the capability. */
|
|
3363
|
+
type FrontDoorSessionSummary = Pick<FrontDoorSession, "pid" | "startedAt">;
|
|
3364
|
+
|
|
3365
|
+
/**
|
|
3366
|
+
* The front door's read-only status: the data `agent-shim frontdoor status` prints and the door's own typed `frontdoor.status` procedure returns, collected without starting or stopping anything. Kept here, beside the state file and session registry it reads, so both the command layer and the typed API's schema layer share one shape and one collector with no dependency on the CLI's command wiring.
|
|
3367
|
+
*/
|
|
3368
|
+
/**
|
|
3369
|
+
* The headroom daemon's socket as the hop may use it, read from the daemon's state on every routed request that needs the hop and authenticated each time: a new supervisor generation serves on a new path while this door keeps listening, and the hop must follow it (and answer 502 while the daemon is between restarts, or refuse a socket that fails the owner-only check). Undefined while no socket is recorded.
|
|
3370
|
+
*/
|
|
3371
|
+
declare function headroomSocketTarget(fsPort: HeadroomFs, trust: HeadroomSocketTrustPorts, paths: LayoutPaths): HeadroomSocketTarget | undefined;
|
|
3372
|
+
/** One session-registry entry plus whether its launcher is still running. */
|
|
3373
|
+
interface FrontDoorSessionStatus extends FrontDoorSessionSummary {
|
|
3374
|
+
readonly alive: boolean;
|
|
3375
|
+
}
|
|
3376
|
+
/** Everything `agent-shim frontdoor status` reports, collected read-only: no process is started or stopped. */
|
|
3377
|
+
interface FrontDoorStatus {
|
|
3378
|
+
readonly state: FrontDoorState;
|
|
3379
|
+
readonly supervisorAlive: boolean;
|
|
3380
|
+
readonly sessions: readonly FrontDoorSessionStatus[];
|
|
3381
|
+
/** The headroom daemon's socket as the door's hop reads and authenticates it live: undefined when no socket is recorded, a refusal when the recorded one fails the owner-only check. */
|
|
3382
|
+
readonly headroomSocket: HeadroomSocketTarget | undefined;
|
|
3383
|
+
readonly logPath: string;
|
|
3384
|
+
readonly logExists: boolean;
|
|
3385
|
+
}
|
|
3386
|
+
/** Collects the front door's read-only status. */
|
|
3387
|
+
declare function collectFrontDoorStatus(fsPort: HeadroomFs, socketTrust: HeadroomSocketTrustPorts, paths: LayoutPaths, isRunning: (pid: number) => boolean): FrontDoorStatus;
|
|
3388
|
+
/** Formats `agent-shim frontdoor status`, one line per entry. */
|
|
3389
|
+
declare function formatFrontDoorStatus(status: FrontDoorStatus, caCertPath: string): string[];
|
|
3390
|
+
|
|
3391
|
+
/**
|
|
3392
|
+
* The door's general control plane as a typed oRPC API: the read-only surfaces a programmatic consumer (automation, a dashboard, another of this user's tools) needs beyond Remote Control, one router per domain, every procedure behind the same per-generation control token as `rc.*` and validating through the Zod schemas of `controlSchemas.ts`.
|
|
3393
|
+
*
|
|
3394
|
+
* - `usage.*` reads the per-identity usage snapshots the door's own middleware writes, and reads a provider's quota windows the way every in-process consumer does (`effectiveWindow`: a window past its reset is empty and carries no status).
|
|
3395
|
+
* - `frontdoor.*` returns what `agent-shim frontdoor status` returns: the supervisor state, its liveness, the session registry's launches and the headroom hop.
|
|
3396
|
+
* - `check.run` and `doctor.run` return the reports `agent-shim check` and `agent-shim doctor` print, as data, `check.run` parameterised by an absolute directory path.
|
|
3397
|
+
*
|
|
3398
|
+
* Read-only by design: identity, configuration-profile, provider, pool and directory-rule management stay CLI-side, and adding writes over this mount is a decision of its own rather than a gap here. `createDoorApiNodeHandler` mounts these routers beside the Remote Control router on the one prefix the provider listener already serves, so a consumer dials one address with one token for the whole door.
|
|
3399
|
+
*/
|
|
3400
|
+
/** Everything the control-plane procedures need, injected so they serve against fakes in tests exactly as the door's real wiring serves against this machine. */
|
|
3401
|
+
interface ControlApiDeps {
|
|
3402
|
+
/** This generation's control token: the same value the Remote Control router checks, since one mount serves both. */
|
|
3403
|
+
readonly expectedToken: string;
|
|
3404
|
+
/** Every identity's usage snapshot, as `listUsageSnapshots` reads them. */
|
|
3405
|
+
readonly usageSnapshots: () => readonly UsageSnapshot[];
|
|
3406
|
+
/** One identity's usage snapshot, as `readUsageSnapshot` reads it: undefined when the identity has none yet. */
|
|
3407
|
+
readonly usageSnapshotOf: (identity: string) => UsageSnapshot | undefined;
|
|
3408
|
+
/** The clock the window semantics read a recorded window at. */
|
|
3409
|
+
readonly now: () => number;
|
|
3410
|
+
/** The door's read-only status, as `collectFrontDoorStatus` collects it. */
|
|
3411
|
+
readonly frontDoorStatus: () => FrontDoorStatus;
|
|
3412
|
+
/** The check report for one directory, as `collectCheckReport` collects it. */
|
|
3413
|
+
readonly checkReport: (path: string, identity?: string) => CheckReport;
|
|
3414
|
+
/** The doctor report, as `collectDoctorReport` collects it. */
|
|
3415
|
+
readonly doctorReport: () => DoctorReport;
|
|
3416
|
+
}
|
|
3417
|
+
/** Builds the control-plane routers: one procedure per read, every one behind the control-token middleware. */
|
|
3418
|
+
declare function createControlApiRouter(deps: ControlApiDeps): {
|
|
3419
|
+
usage: {
|
|
3420
|
+
list: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, Schema<unknown, unknown>, zod.ZodObject<{
|
|
3421
|
+
snapshots: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
3422
|
+
schemaVersion: zod.ZodLiteral<1>;
|
|
3423
|
+
identity: zod.ZodString;
|
|
3424
|
+
updatedAt: zod.ZodISODateTime;
|
|
3425
|
+
account: zod.ZodOptional<zod.ZodObject<{
|
|
3426
|
+
accountUuid: zod.ZodOptional<zod.ZodString>;
|
|
3427
|
+
emailAddress: zod.ZodOptional<zod.ZodString>;
|
|
3428
|
+
displayName: zod.ZodOptional<zod.ZodString>;
|
|
3429
|
+
organizationUuid: zod.ZodOptional<zod.ZodString>;
|
|
3430
|
+
organizationName: zod.ZodOptional<zod.ZodString>;
|
|
3431
|
+
organizationType: zod.ZodOptional<zod.ZodString>;
|
|
3432
|
+
organizationRole: zod.ZodOptional<zod.ZodString>;
|
|
3433
|
+
workspaceRole: zod.ZodOptional<zod.ZodString>;
|
|
3434
|
+
billingType: zod.ZodOptional<zod.ZodString>;
|
|
3435
|
+
seatTier: zod.ZodOptional<zod.ZodString>;
|
|
3436
|
+
organizationRateLimitTier: zod.ZodOptional<zod.ZodString>;
|
|
3437
|
+
userRateLimitTier: zod.ZodOptional<zod.ZodString>;
|
|
3438
|
+
hasExtraUsageEnabled: zod.ZodOptional<zod.ZodBoolean>;
|
|
3439
|
+
subscriptionCreatedAt: zod.ZodOptional<zod.ZodString>;
|
|
3440
|
+
accountCreatedAt: zod.ZodOptional<zod.ZodString>;
|
|
3441
|
+
}, zod_v4_core.$strict>>;
|
|
3442
|
+
providers: zod.ZodRecord<zod.ZodString, zod.ZodObject<{
|
|
3443
|
+
lastRequestAt: zod.ZodISODateTime;
|
|
3444
|
+
lastStatus: zod.ZodNumber;
|
|
3445
|
+
lastModel: zod.ZodOptional<zod.ZodString>;
|
|
3446
|
+
rateLimit: zod.ZodOptional<zod.ZodObject<{
|
|
3447
|
+
observedAt: zod.ZodISODateTime;
|
|
3448
|
+
headers: zod.ZodRecord<zod.ZodString, zod.ZodString>;
|
|
3449
|
+
unified: zod.ZodOptional<zod.ZodObject<{
|
|
3450
|
+
status: zod.ZodOptional<zod.ZodString>;
|
|
3451
|
+
fiveHour: zod.ZodOptional<zod.ZodObject<{
|
|
3452
|
+
utilization: zod.ZodOptional<zod.ZodNumber>;
|
|
3453
|
+
resetsAt: zod.ZodOptional<zod.ZodISODateTime>;
|
|
3454
|
+
status: zod.ZodOptional<zod.ZodString>;
|
|
3455
|
+
}, zod_v4_core.$strict>>;
|
|
3456
|
+
sevenDay: zod.ZodOptional<zod.ZodObject<{
|
|
3457
|
+
utilization: zod.ZodOptional<zod.ZodNumber>;
|
|
3458
|
+
resetsAt: zod.ZodOptional<zod.ZodISODateTime>;
|
|
3459
|
+
status: zod.ZodOptional<zod.ZodString>;
|
|
3460
|
+
}, zod_v4_core.$strict>>;
|
|
3461
|
+
representativeClaim: zod.ZodOptional<zod.ZodString>;
|
|
3462
|
+
resetAt: zod.ZodOptional<zod.ZodISODateTime>;
|
|
3463
|
+
overageStatus: zod.ZodOptional<zod.ZodString>;
|
|
3464
|
+
}, zod_v4_core.$strict>>;
|
|
3465
|
+
}, zod_v4_core.$strict>>;
|
|
3466
|
+
lastLimit: zod.ZodOptional<zod.ZodObject<{
|
|
3467
|
+
kind: zod.ZodEnum<{
|
|
3468
|
+
"rate-limited": "rate-limited";
|
|
3469
|
+
"quota-exhausted": "quota-exhausted";
|
|
3470
|
+
}>;
|
|
3471
|
+
retryAfterSeconds: zod.ZodOptional<zod.ZodNumber>;
|
|
3472
|
+
resetAt: zod.ZodOptional<zod.ZodISODateTime>;
|
|
3473
|
+
window: zod.ZodOptional<zod.ZodString>;
|
|
3474
|
+
evidence: zod.ZodArray<zod.ZodString>;
|
|
3475
|
+
observedAt: zod.ZodISODateTime;
|
|
3476
|
+
status: zod.ZodNumber;
|
|
3477
|
+
}, zod_v4_core.$strict>>;
|
|
3478
|
+
quota: zod.ZodOptional<zod.ZodObject<{
|
|
3479
|
+
observedAt: zod.ZodISODateTime;
|
|
3480
|
+
source: zod.ZodString;
|
|
3481
|
+
level: zod.ZodOptional<zod.ZodString>;
|
|
3482
|
+
windows: zod.ZodArray<zod.ZodObject<{
|
|
3483
|
+
measures: zod.ZodString;
|
|
3484
|
+
periodMs: zod.ZodOptional<zod.ZodNumber>;
|
|
3485
|
+
period: zod.ZodOptional<zod.ZodString>;
|
|
3486
|
+
utilization: zod.ZodNumber;
|
|
3487
|
+
resetsAt: zod.ZodOptional<zod.ZodISODateTime>;
|
|
3488
|
+
limit: zod.ZodOptional<zod.ZodNumber>;
|
|
3489
|
+
used: zod.ZodOptional<zod.ZodNumber>;
|
|
3490
|
+
remaining: zod.ZodOptional<zod.ZodNumber>;
|
|
3491
|
+
}, zod_v4_core.$strict>>;
|
|
3492
|
+
}, zod_v4_core.$strict>>;
|
|
3493
|
+
}, zod_v4_core.$strict>>;
|
|
3494
|
+
}, zod_v4_core.$strict>>>;
|
|
3495
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
3496
|
+
effectiveWindow: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
3497
|
+
identity: zod.ZodString;
|
|
3498
|
+
provider: zod.ZodOptional<zod.ZodString>;
|
|
3499
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3500
|
+
identity: zod.ZodString;
|
|
3501
|
+
provider: zod.ZodString;
|
|
3502
|
+
observedAt: zod.ZodOptional<zod.ZodISODateTime>;
|
|
3503
|
+
fiveHour: zod.ZodOptional<zod.ZodObject<{
|
|
3504
|
+
reset: zod.ZodBoolean;
|
|
3505
|
+
utilization: zod.ZodOptional<zod.ZodNumber>;
|
|
3506
|
+
resetsAtMs: zod.ZodOptional<zod.ZodNumber>;
|
|
3507
|
+
status: zod.ZodOptional<zod.ZodString>;
|
|
3508
|
+
}, zod_v4_core.$strict>>;
|
|
3509
|
+
sevenDay: zod.ZodOptional<zod.ZodObject<{
|
|
3510
|
+
reset: zod.ZodBoolean;
|
|
3511
|
+
utilization: zod.ZodOptional<zod.ZodNumber>;
|
|
3512
|
+
resetsAtMs: zod.ZodOptional<zod.ZodNumber>;
|
|
3513
|
+
status: zod.ZodOptional<zod.ZodString>;
|
|
3514
|
+
}, zod_v4_core.$strict>>;
|
|
3515
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
3516
|
+
};
|
|
3517
|
+
frontdoor: {
|
|
3518
|
+
status: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, Schema<unknown, unknown>, zod.ZodObject<{
|
|
3519
|
+
state: zod.ZodObject<{
|
|
3520
|
+
protocol: zod.ZodOptional<zod.ZodNumber>;
|
|
3521
|
+
supervisorPid: zod.ZodOptional<zod.ZodNumber>;
|
|
3522
|
+
port: zod.ZodOptional<zod.ZodNumber>;
|
|
3523
|
+
lastPort: zod.ZodOptional<zod.ZodNumber>;
|
|
3524
|
+
connectPort: zod.ZodOptional<zod.ZodNumber>;
|
|
3525
|
+
lastConnectPort: zod.ZodOptional<zod.ZodNumber>;
|
|
3526
|
+
directPort: zod.ZodOptional<zod.ZodNumber>;
|
|
3527
|
+
lastDirectPort: zod.ZodOptional<zod.ZodNumber>;
|
|
3528
|
+
lastError: zod.ZodOptional<zod.ZodString>;
|
|
3529
|
+
}, zod_v4_core.$strict>;
|
|
3530
|
+
supervisorAlive: zod.ZodBoolean;
|
|
3531
|
+
sessions: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
3532
|
+
pid: zod.ZodInt;
|
|
3533
|
+
startedAt: zod.ZodNumber;
|
|
3534
|
+
alive: zod.ZodBoolean;
|
|
3535
|
+
}, zod_v4_core.$strict>>>;
|
|
3536
|
+
headroomSocket: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodObject<{
|
|
3537
|
+
socketPath: zod.ZodString;
|
|
3538
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3539
|
+
refused: zod.ZodString;
|
|
3540
|
+
}, zod_v4_core.$strict>]>>;
|
|
3541
|
+
logPath: zod.ZodString;
|
|
3542
|
+
logExists: zod.ZodBoolean;
|
|
3543
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
3544
|
+
sessions: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, Schema<unknown, unknown>, zod.ZodObject<{
|
|
3545
|
+
sessions: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
3546
|
+
pid: zod.ZodInt;
|
|
3547
|
+
startedAt: zod.ZodNumber;
|
|
3548
|
+
alive: zod.ZodBoolean;
|
|
3549
|
+
}, zod_v4_core.$strict>>>;
|
|
3550
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
3551
|
+
};
|
|
3552
|
+
check: {
|
|
3553
|
+
run: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
3554
|
+
path: zod.ZodString;
|
|
3555
|
+
identity: zod.ZodOptional<zod.ZodString>;
|
|
3556
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3557
|
+
identity: zod.ZodObject<{
|
|
3558
|
+
name: zod.ZodNullable<zod.ZodString>;
|
|
3559
|
+
source: zod.ZodEnum<{
|
|
3560
|
+
"config-dir-escape-hatch": "config-dir-escape-hatch";
|
|
3561
|
+
argv: "argv";
|
|
3562
|
+
env: "env";
|
|
3563
|
+
"directory-pin": "directory-pin";
|
|
3564
|
+
"active-identity-file": "active-identity-file";
|
|
3565
|
+
none: "none";
|
|
3566
|
+
}>;
|
|
3567
|
+
}, zod_v4_core.$strict>;
|
|
3568
|
+
pool: zod.ZodOptional<zod.ZodObject<{
|
|
3569
|
+
pool: zod.ZodString;
|
|
3570
|
+
directory: zod.ZodString;
|
|
3571
|
+
pick: zod.ZodOptional<zod.ZodString>;
|
|
3572
|
+
candidates: zod.ZodArray<zod.ZodObject<{
|
|
3573
|
+
identity: zod.ZodString;
|
|
3574
|
+
class: zod.ZodEnum<{
|
|
3575
|
+
unknown: "unknown";
|
|
3576
|
+
scored: "scored";
|
|
3577
|
+
"pay-per-use": "pay-per-use";
|
|
3578
|
+
ineligible: "ineligible";
|
|
3579
|
+
}>;
|
|
3580
|
+
score: zod.ZodOptional<zod.ZodNumber>;
|
|
3581
|
+
feasible: zod.ZodBoolean;
|
|
3582
|
+
blockedUntil: zod.ZodOptional<zod.ZodISODateTime>;
|
|
3583
|
+
plan: zod.ZodUnion<readonly [zod.ZodObject<{
|
|
3584
|
+
kind: zod.ZodLiteral<"subscription">;
|
|
3585
|
+
capacity: zod.ZodNumber;
|
|
3586
|
+
recognised: zod.ZodBoolean;
|
|
3587
|
+
tier: zod.ZodOptional<zod.ZodString>;
|
|
3588
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3589
|
+
kind: zod.ZodLiteral<"pay-per-use">;
|
|
3590
|
+
tier: zod.ZodOptional<zod.ZodString>;
|
|
3591
|
+
}, zod_v4_core.$strict>]>;
|
|
3592
|
+
reasons: zod.ZodArray<zod.ZodString>;
|
|
3593
|
+
}, zod_v4_core.$strict>>;
|
|
3594
|
+
missing: zod.ZodArray<zod.ZodString>;
|
|
3595
|
+
earliestReturn: zod.ZodOptional<zod.ZodObject<{
|
|
3596
|
+
identity: zod.ZodString;
|
|
3597
|
+
at: zod.ZodISODateTime;
|
|
3598
|
+
}, zod_v4_core.$strict>>;
|
|
3599
|
+
stickyProblem: zod.ZodOptional<zod.ZodString>;
|
|
3600
|
+
}, zod_v4_core.$strict>>;
|
|
3601
|
+
configProfile: zod.ZodObject<{
|
|
3602
|
+
name: zod.ZodNullable<zod.ZodString>;
|
|
3603
|
+
source: zod.ZodEnum<{
|
|
3604
|
+
"directory-rule": "directory-rule";
|
|
3605
|
+
env: "env";
|
|
3606
|
+
none: "none";
|
|
3607
|
+
"cli-flag": "cli-flag";
|
|
3608
|
+
"identity-default": "identity-default";
|
|
3609
|
+
"global-default": "global-default";
|
|
3610
|
+
}>;
|
|
3611
|
+
}, zod_v4_core.$strict>;
|
|
3612
|
+
layers: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
3613
|
+
id: zod.ZodInt;
|
|
3614
|
+
kind: zod.ZodEnum<{
|
|
3615
|
+
"global-config": "global-config";
|
|
3616
|
+
"config-profile": "config-profile";
|
|
3617
|
+
"directory-rule": "directory-rule";
|
|
3618
|
+
portable: "portable";
|
|
3619
|
+
"portable-local": "portable-local";
|
|
3620
|
+
"cli-override": "cli-override";
|
|
3621
|
+
}>;
|
|
3622
|
+
source: zod.ZodString;
|
|
3623
|
+
}, zod_v4_core.$strict>>>;
|
|
3624
|
+
entries: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
3625
|
+
path: zod.ZodString;
|
|
3626
|
+
shared: zod.ZodBoolean;
|
|
3627
|
+
via: zod.ZodEnum<{
|
|
3628
|
+
"secret-floor": "secret-floor";
|
|
3629
|
+
unclassified: "unclassified";
|
|
3630
|
+
"entry-rule": "entry-rule";
|
|
3631
|
+
"category-override": "category-override";
|
|
3632
|
+
"category-default": "category-default";
|
|
3633
|
+
}>;
|
|
3634
|
+
category: zod.ZodNullable<zod.ZodEnum<{
|
|
3635
|
+
secret: "secret";
|
|
3636
|
+
runtime: "runtime";
|
|
3637
|
+
history: "history";
|
|
3638
|
+
knowledge: "knowledge";
|
|
3639
|
+
settings: "settings";
|
|
3640
|
+
}>>;
|
|
3641
|
+
rule: zod.ZodOptional<zod.ZodObject<{
|
|
3642
|
+
key: zod.ZodString;
|
|
3643
|
+
layer: zod.ZodInt;
|
|
3644
|
+
}, zod_v4_core.$strict>>;
|
|
3645
|
+
eliminated: zod.ZodOptional<zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
3646
|
+
key: zod.ZodString;
|
|
3647
|
+
failed: zod.ZodReadonly<zod.ZodArray<zod.ZodString>>;
|
|
3648
|
+
}, zod_v4_core.$strict>>>>;
|
|
3649
|
+
}, zod_v4_core.$strict>>>;
|
|
3650
|
+
projectEncodingAmbiguities: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
3651
|
+
fragment: zod.ZodString;
|
|
3652
|
+
encoded: zod.ZodString;
|
|
3653
|
+
reason: zod.ZodEnum<{
|
|
3654
|
+
"lossy-characters": "lossy-characters";
|
|
3655
|
+
"collides-with-sibling-pattern": "collides-with-sibling-pattern";
|
|
3656
|
+
}>;
|
|
3657
|
+
detail: zod.ZodString;
|
|
3658
|
+
}, zod_v4_core.$strict>>>;
|
|
3659
|
+
diagnostics: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
3660
|
+
code: zod.ZodEnum<{
|
|
3661
|
+
EXTENDS_CYCLE: "EXTENDS_CYCLE";
|
|
3662
|
+
MISSING_PROFILE: "MISSING_PROFILE";
|
|
3663
|
+
SECRET_ENTRY_KEY: "SECRET_ENTRY_KEY";
|
|
3664
|
+
SECRET_PATH_NEUTRALISED: "SECRET_PATH_NEUTRALISED";
|
|
3665
|
+
CATEGORY_PREFIX_MISMATCH: "CATEGORY_PREFIX_MISMATCH";
|
|
3666
|
+
MALFORMED_ENTRY_KEY: "MALFORMED_ENTRY_KEY";
|
|
3667
|
+
EXACT_ENTRY_OVERRIDDEN_BY_LATER_GLOB: "EXACT_ENTRY_OVERRIDDEN_BY_LATER_GLOB";
|
|
3668
|
+
AMBIGUOUS_PROJECT_ENCODING: "AMBIGUOUS_PROJECT_ENCODING";
|
|
3669
|
+
UNROOTED_PROJECT_PATH: "UNROOTED_PROJECT_PATH";
|
|
3670
|
+
UNCLASSIFIED_ENTRY: "UNCLASSIFIED_ENTRY";
|
|
3671
|
+
EMPTY_WHEN: "EMPTY_WHEN";
|
|
3672
|
+
FARM_MANIFEST_MISSING: "FARM_MANIFEST_MISSING";
|
|
3673
|
+
RECONCILE_CONFLICT: "RECONCILE_CONFLICT";
|
|
3674
|
+
RECONCILE_SECRET_BLOCKED: "RECONCILE_SECRET_BLOCKED";
|
|
3675
|
+
FARM_SWAP_RECOVERED: "FARM_SWAP_RECOVERED";
|
|
3676
|
+
FARM_PREVIOUS_RETAINED: "FARM_PREVIOUS_RETAINED";
|
|
3677
|
+
}>;
|
|
3678
|
+
severity: zod.ZodEnum<{
|
|
3679
|
+
error: "error";
|
|
3680
|
+
warning: "warning";
|
|
3681
|
+
info: "info";
|
|
3682
|
+
}>;
|
|
3683
|
+
message: zod.ZodString;
|
|
3684
|
+
subject: zod.ZodOptional<zod.ZodString>;
|
|
3685
|
+
layer: zod.ZodOptional<zod.ZodInt>;
|
|
3686
|
+
}, zod_v4_core.$strict>>>;
|
|
3687
|
+
ambientCredential: zod.ZodUnion<readonly [zod.ZodObject<{
|
|
3688
|
+
ok: zod.ZodLiteral<true>;
|
|
3689
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3690
|
+
ok: zod.ZodLiteral<false>;
|
|
3691
|
+
variable: zod.ZodString;
|
|
3692
|
+
message: zod.ZodString;
|
|
3693
|
+
}, zod_v4_core.$strict>]>;
|
|
3694
|
+
keychain: zod.ZodOptional<zod.ZodObject<{
|
|
3695
|
+
checked: zod.ZodLiteral<true>;
|
|
3696
|
+
found: zod.ZodBoolean;
|
|
3697
|
+
serviceName: zod.ZodOptional<zod.ZodString>;
|
|
3698
|
+
note: zod.ZodString;
|
|
3699
|
+
}, zod_v4_core.$strict>>;
|
|
3700
|
+
settingsExposure: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
3701
|
+
file: zod.ZodString;
|
|
3702
|
+
envKeyNames: zod.ZodReadonly<zod.ZodArray<zod.ZodString>>;
|
|
3703
|
+
hookEventNames: zod.ZodReadonly<zod.ZodArray<zod.ZodString>>;
|
|
3704
|
+
hookCommandCount: zod.ZodInt;
|
|
3705
|
+
}, zod_v4_core.$strict>>>;
|
|
3706
|
+
credential: zod.ZodObject<{
|
|
3707
|
+
applies: zod.ZodEnum<{
|
|
3708
|
+
identity: "identity";
|
|
3709
|
+
provider: "provider";
|
|
3710
|
+
"stored-login": "stored-login";
|
|
3711
|
+
}>;
|
|
3712
|
+
provider: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodObject<{
|
|
3713
|
+
name: zod.ZodString;
|
|
3714
|
+
credential: zod.ZodObject<{
|
|
3715
|
+
target: zod.ZodEnum<{
|
|
3716
|
+
bearer: "bearer";
|
|
3717
|
+
apiKey: "apiKey";
|
|
3718
|
+
oauthToken: "oauthToken";
|
|
3719
|
+
}>;
|
|
3720
|
+
sources: zod.ZodReadonly<zod.ZodArray<zod.ZodUnion<readonly [zod.ZodObject<{
|
|
3721
|
+
kind: zod.ZodLiteral<"env">;
|
|
3722
|
+
variable: zod.ZodString;
|
|
3723
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3724
|
+
kind: zod.ZodLiteral<"file">;
|
|
3725
|
+
path: zod.ZodString;
|
|
3726
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3727
|
+
kind: zod.ZodLiteral<"command">;
|
|
3728
|
+
program: zod.ZodString;
|
|
3729
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3730
|
+
kind: zod.ZodLiteral<"op">;
|
|
3731
|
+
reference: zod.ZodString;
|
|
3732
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3733
|
+
kind: zod.ZodLiteral<"keychain">;
|
|
3734
|
+
service: zod.ZodString;
|
|
3735
|
+
account: zod.ZodOptional<zod.ZodString>;
|
|
3736
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3737
|
+
kind: zod.ZodLiteral<"literal">;
|
|
3738
|
+
}, zod_v4_core.$strict>]>>>;
|
|
3739
|
+
cache: zod.ZodOptional<zod.ZodObject<{
|
|
3740
|
+
ttl: zod.ZodOptional<zod.ZodString>;
|
|
3741
|
+
store: zod.ZodOptional<zod.ZodEnum<{
|
|
3742
|
+
file: "file";
|
|
3743
|
+
keychain: "keychain";
|
|
3744
|
+
}>>;
|
|
3745
|
+
}, zod_v4_core.$strict>>;
|
|
3746
|
+
}, zod_v4_core.$strict>;
|
|
3747
|
+
cached: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodObject<{
|
|
3748
|
+
store: zod.ZodEnum<{
|
|
3749
|
+
file: "file";
|
|
3750
|
+
keychain: "keychain";
|
|
3751
|
+
}>;
|
|
3752
|
+
status: zod.ZodLiteral<"empty">;
|
|
3753
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3754
|
+
store: zod.ZodEnum<{
|
|
3755
|
+
file: "file";
|
|
3756
|
+
keychain: "keychain";
|
|
3757
|
+
}>;
|
|
3758
|
+
status: zod.ZodLiteral<"unreadable">;
|
|
3759
|
+
reason: zod.ZodString;
|
|
3760
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3761
|
+
store: zod.ZodEnum<{
|
|
3762
|
+
file: "file";
|
|
3763
|
+
keychain: "keychain";
|
|
3764
|
+
}>;
|
|
3765
|
+
status: zod.ZodEnum<{
|
|
3766
|
+
fresh: "fresh";
|
|
3767
|
+
expired: "expired";
|
|
3768
|
+
}>;
|
|
3769
|
+
ageMs: zod.ZodNumber;
|
|
3770
|
+
expiresInMs: zod.ZodOptional<zod.ZodNumber>;
|
|
3771
|
+
}, zod_v4_core.$strict>]>>;
|
|
3772
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3773
|
+
name: zod.ZodString;
|
|
3774
|
+
problem: zod.ZodString;
|
|
3775
|
+
}, zod_v4_core.$strict>]>>;
|
|
3776
|
+
identity: zod.ZodOptional<zod.ZodObject<{
|
|
3777
|
+
target: zod.ZodEnum<{
|
|
3778
|
+
bearer: "bearer";
|
|
3779
|
+
apiKey: "apiKey";
|
|
3780
|
+
oauthToken: "oauthToken";
|
|
3781
|
+
}>;
|
|
3782
|
+
sources: zod.ZodReadonly<zod.ZodArray<zod.ZodUnion<readonly [zod.ZodObject<{
|
|
3783
|
+
kind: zod.ZodLiteral<"env">;
|
|
3784
|
+
variable: zod.ZodString;
|
|
3785
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3786
|
+
kind: zod.ZodLiteral<"file">;
|
|
3787
|
+
path: zod.ZodString;
|
|
3788
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3789
|
+
kind: zod.ZodLiteral<"command">;
|
|
3790
|
+
program: zod.ZodString;
|
|
3791
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3792
|
+
kind: zod.ZodLiteral<"op">;
|
|
3793
|
+
reference: zod.ZodString;
|
|
3794
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3795
|
+
kind: zod.ZodLiteral<"keychain">;
|
|
3796
|
+
service: zod.ZodString;
|
|
3797
|
+
account: zod.ZodOptional<zod.ZodString>;
|
|
3798
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3799
|
+
kind: zod.ZodLiteral<"literal">;
|
|
3800
|
+
}, zod_v4_core.$strict>]>>>;
|
|
3801
|
+
cache: zod.ZodOptional<zod.ZodObject<{
|
|
3802
|
+
ttl: zod.ZodOptional<zod.ZodString>;
|
|
3803
|
+
store: zod.ZodOptional<zod.ZodEnum<{
|
|
3804
|
+
file: "file";
|
|
3805
|
+
keychain: "keychain";
|
|
3806
|
+
}>>;
|
|
3807
|
+
}, zod_v4_core.$strict>>;
|
|
3808
|
+
}, zod_v4_core.$strict>>;
|
|
3809
|
+
identityCached: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodObject<{
|
|
3810
|
+
store: zod.ZodEnum<{
|
|
3811
|
+
file: "file";
|
|
3812
|
+
keychain: "keychain";
|
|
3813
|
+
}>;
|
|
3814
|
+
status: zod.ZodLiteral<"empty">;
|
|
3815
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3816
|
+
store: zod.ZodEnum<{
|
|
3817
|
+
file: "file";
|
|
3818
|
+
keychain: "keychain";
|
|
3819
|
+
}>;
|
|
3820
|
+
status: zod.ZodLiteral<"unreadable">;
|
|
3821
|
+
reason: zod.ZodString;
|
|
3822
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3823
|
+
store: zod.ZodEnum<{
|
|
3824
|
+
file: "file";
|
|
3825
|
+
keychain: "keychain";
|
|
3826
|
+
}>;
|
|
3827
|
+
status: zod.ZodEnum<{
|
|
3828
|
+
fresh: "fresh";
|
|
3829
|
+
expired: "expired";
|
|
3830
|
+
}>;
|
|
3831
|
+
ageMs: zod.ZodNumber;
|
|
3832
|
+
expiresInMs: zod.ZodOptional<zod.ZodNumber>;
|
|
3833
|
+
}, zod_v4_core.$strict>]>>;
|
|
3834
|
+
}, zod_v4_core.$strict>;
|
|
3835
|
+
claudeVersion: zod.ZodOptional<zod.ZodObject<{
|
|
3836
|
+
pinned: zod.ZodOptional<zod.ZodObject<{
|
|
3837
|
+
version: zod.ZodString;
|
|
3838
|
+
source: zod.ZodEnum<{
|
|
3839
|
+
flag: "flag";
|
|
3840
|
+
environment: "environment";
|
|
3841
|
+
cascade: "cascade";
|
|
3842
|
+
}>;
|
|
3843
|
+
installed: zod.ZodBoolean;
|
|
3844
|
+
}, zod_v4_core.$strict>>;
|
|
3845
|
+
highestInstalled: zod.ZodOptional<zod.ZodString>;
|
|
3846
|
+
installed: zod.ZodReadonly<zod.ZodArray<zod.ZodString>>;
|
|
3847
|
+
}, zod_v4_core.$strict>>;
|
|
3848
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
3849
|
+
};
|
|
3850
|
+
doctor: {
|
|
3851
|
+
run: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, Schema<unknown, unknown>, zod.ZodObject<{
|
|
3852
|
+
ok: zod.ZodBoolean;
|
|
3853
|
+
findings: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
3854
|
+
section: zod.ZodEnum<{
|
|
3855
|
+
"global-config": "global-config";
|
|
3856
|
+
"config-profile": "config-profile";
|
|
3857
|
+
identity: "identity";
|
|
3858
|
+
provider: "provider";
|
|
3859
|
+
pool: "pool";
|
|
3860
|
+
keychain: "keychain";
|
|
3861
|
+
"ambient-credential": "ambient-credential";
|
|
3862
|
+
"binary-discovery": "binary-discovery";
|
|
3863
|
+
"claude-shim": "claude-shim";
|
|
3864
|
+
"path-resolution": "path-resolution";
|
|
3865
|
+
"legacy-name": "legacy-name";
|
|
3866
|
+
"directory-rules": "directory-rules";
|
|
3867
|
+
"categories-local": "categories-local";
|
|
3868
|
+
"active-identity": "active-identity";
|
|
3869
|
+
headroom: "headroom";
|
|
3870
|
+
}>;
|
|
3871
|
+
subject: zod.ZodOptional<zod.ZodString>;
|
|
3872
|
+
severity: zod.ZodEnum<{
|
|
3873
|
+
pass: "pass";
|
|
3874
|
+
warn: "warn";
|
|
3875
|
+
fail: "fail";
|
|
3876
|
+
}>;
|
|
3877
|
+
message: zod.ZodString;
|
|
3878
|
+
}, zod_v4_core.$strict>>>;
|
|
3879
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
3880
|
+
};
|
|
3881
|
+
};
|
|
3882
|
+
/** The control-plane routers, as the merged mount's and the client's own types are derived from them. */
|
|
3883
|
+
type ControlApiRouter = ReturnType<typeof createControlApiRouter>;
|
|
3884
|
+
/** The control plane alone as a client sees it: every call presents the control token, over TLS trusting only the CA file the door's own state names. */
|
|
3885
|
+
type ControlApiClient = RouterClient<ControlApiRouter>;
|
|
3886
|
+
/** Everything the door's whole typed API needs: the Remote Control operations and the control-plane reads, one deps object because one mount serves them under one token. */
|
|
3887
|
+
interface DoorApiDeps extends RcApiDeps, ControlApiDeps {
|
|
3888
|
+
}
|
|
3889
|
+
/** Builds the door's whole typed API: the Remote Control router and the control-plane routers beside it, one object for the one handler the provider listener mounts. */
|
|
3890
|
+
declare function createDoorApiRouter(deps: DoorApiDeps): {
|
|
3891
|
+
usage: {
|
|
3892
|
+
list: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, Schema<unknown, unknown>, zod.ZodObject<{
|
|
3893
|
+
snapshots: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
3894
|
+
schemaVersion: zod.ZodLiteral<1>;
|
|
3895
|
+
identity: zod.ZodString;
|
|
3896
|
+
updatedAt: zod.ZodISODateTime;
|
|
3897
|
+
account: zod.ZodOptional<zod.ZodObject<{
|
|
3898
|
+
accountUuid: zod.ZodOptional<zod.ZodString>;
|
|
3899
|
+
emailAddress: zod.ZodOptional<zod.ZodString>;
|
|
3900
|
+
displayName: zod.ZodOptional<zod.ZodString>;
|
|
3901
|
+
organizationUuid: zod.ZodOptional<zod.ZodString>;
|
|
3902
|
+
organizationName: zod.ZodOptional<zod.ZodString>;
|
|
3903
|
+
organizationType: zod.ZodOptional<zod.ZodString>;
|
|
3904
|
+
organizationRole: zod.ZodOptional<zod.ZodString>;
|
|
3905
|
+
workspaceRole: zod.ZodOptional<zod.ZodString>;
|
|
3906
|
+
billingType: zod.ZodOptional<zod.ZodString>;
|
|
3907
|
+
seatTier: zod.ZodOptional<zod.ZodString>;
|
|
3908
|
+
organizationRateLimitTier: zod.ZodOptional<zod.ZodString>;
|
|
3909
|
+
userRateLimitTier: zod.ZodOptional<zod.ZodString>;
|
|
3910
|
+
hasExtraUsageEnabled: zod.ZodOptional<zod.ZodBoolean>;
|
|
3911
|
+
subscriptionCreatedAt: zod.ZodOptional<zod.ZodString>;
|
|
3912
|
+
accountCreatedAt: zod.ZodOptional<zod.ZodString>;
|
|
3913
|
+
}, zod_v4_core.$strict>>;
|
|
3914
|
+
providers: zod.ZodRecord<zod.ZodString, zod.ZodObject<{
|
|
3915
|
+
lastRequestAt: zod.ZodISODateTime;
|
|
3916
|
+
lastStatus: zod.ZodNumber;
|
|
3917
|
+
lastModel: zod.ZodOptional<zod.ZodString>;
|
|
3918
|
+
rateLimit: zod.ZodOptional<zod.ZodObject<{
|
|
3919
|
+
observedAt: zod.ZodISODateTime;
|
|
3920
|
+
headers: zod.ZodRecord<zod.ZodString, zod.ZodString>;
|
|
3921
|
+
unified: zod.ZodOptional<zod.ZodObject<{
|
|
3922
|
+
status: zod.ZodOptional<zod.ZodString>;
|
|
3923
|
+
fiveHour: zod.ZodOptional<zod.ZodObject<{
|
|
3924
|
+
utilization: zod.ZodOptional<zod.ZodNumber>;
|
|
3925
|
+
resetsAt: zod.ZodOptional<zod.ZodISODateTime>;
|
|
3926
|
+
status: zod.ZodOptional<zod.ZodString>;
|
|
3927
|
+
}, zod_v4_core.$strict>>;
|
|
3928
|
+
sevenDay: zod.ZodOptional<zod.ZodObject<{
|
|
3929
|
+
utilization: zod.ZodOptional<zod.ZodNumber>;
|
|
3930
|
+
resetsAt: zod.ZodOptional<zod.ZodISODateTime>;
|
|
3931
|
+
status: zod.ZodOptional<zod.ZodString>;
|
|
3932
|
+
}, zod_v4_core.$strict>>;
|
|
3933
|
+
representativeClaim: zod.ZodOptional<zod.ZodString>;
|
|
3934
|
+
resetAt: zod.ZodOptional<zod.ZodISODateTime>;
|
|
3935
|
+
overageStatus: zod.ZodOptional<zod.ZodString>;
|
|
3936
|
+
}, zod_v4_core.$strict>>;
|
|
3937
|
+
}, zod_v4_core.$strict>>;
|
|
3938
|
+
lastLimit: zod.ZodOptional<zod.ZodObject<{
|
|
3939
|
+
kind: zod.ZodEnum<{
|
|
3940
|
+
"rate-limited": "rate-limited";
|
|
3941
|
+
"quota-exhausted": "quota-exhausted";
|
|
3942
|
+
}>;
|
|
3943
|
+
retryAfterSeconds: zod.ZodOptional<zod.ZodNumber>;
|
|
3944
|
+
resetAt: zod.ZodOptional<zod.ZodISODateTime>;
|
|
3945
|
+
window: zod.ZodOptional<zod.ZodString>;
|
|
3946
|
+
evidence: zod.ZodArray<zod.ZodString>;
|
|
3947
|
+
observedAt: zod.ZodISODateTime;
|
|
3948
|
+
status: zod.ZodNumber;
|
|
3949
|
+
}, zod_v4_core.$strict>>;
|
|
3950
|
+
quota: zod.ZodOptional<zod.ZodObject<{
|
|
3951
|
+
observedAt: zod.ZodISODateTime;
|
|
3952
|
+
source: zod.ZodString;
|
|
3953
|
+
level: zod.ZodOptional<zod.ZodString>;
|
|
3954
|
+
windows: zod.ZodArray<zod.ZodObject<{
|
|
3955
|
+
measures: zod.ZodString;
|
|
3956
|
+
periodMs: zod.ZodOptional<zod.ZodNumber>;
|
|
3957
|
+
period: zod.ZodOptional<zod.ZodString>;
|
|
3958
|
+
utilization: zod.ZodNumber;
|
|
3959
|
+
resetsAt: zod.ZodOptional<zod.ZodISODateTime>;
|
|
3960
|
+
limit: zod.ZodOptional<zod.ZodNumber>;
|
|
3961
|
+
used: zod.ZodOptional<zod.ZodNumber>;
|
|
3962
|
+
remaining: zod.ZodOptional<zod.ZodNumber>;
|
|
3963
|
+
}, zod_v4_core.$strict>>;
|
|
3964
|
+
}, zod_v4_core.$strict>>;
|
|
3965
|
+
}, zod_v4_core.$strict>>;
|
|
3966
|
+
}, zod_v4_core.$strict>>>;
|
|
3967
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
3968
|
+
effectiveWindow: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
3969
|
+
identity: zod.ZodString;
|
|
3970
|
+
provider: zod.ZodOptional<zod.ZodString>;
|
|
3971
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
3972
|
+
identity: zod.ZodString;
|
|
3973
|
+
provider: zod.ZodString;
|
|
3974
|
+
observedAt: zod.ZodOptional<zod.ZodISODateTime>;
|
|
3975
|
+
fiveHour: zod.ZodOptional<zod.ZodObject<{
|
|
3976
|
+
reset: zod.ZodBoolean;
|
|
3977
|
+
utilization: zod.ZodOptional<zod.ZodNumber>;
|
|
3978
|
+
resetsAtMs: zod.ZodOptional<zod.ZodNumber>;
|
|
3979
|
+
status: zod.ZodOptional<zod.ZodString>;
|
|
3980
|
+
}, zod_v4_core.$strict>>;
|
|
3981
|
+
sevenDay: zod.ZodOptional<zod.ZodObject<{
|
|
3982
|
+
reset: zod.ZodBoolean;
|
|
3983
|
+
utilization: zod.ZodOptional<zod.ZodNumber>;
|
|
3984
|
+
resetsAtMs: zod.ZodOptional<zod.ZodNumber>;
|
|
3985
|
+
status: zod.ZodOptional<zod.ZodString>;
|
|
3986
|
+
}, zod_v4_core.$strict>>;
|
|
3987
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
3988
|
+
};
|
|
3989
|
+
frontdoor: {
|
|
3990
|
+
status: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, Schema<unknown, unknown>, zod.ZodObject<{
|
|
3991
|
+
state: zod.ZodObject<{
|
|
3992
|
+
protocol: zod.ZodOptional<zod.ZodNumber>;
|
|
3993
|
+
supervisorPid: zod.ZodOptional<zod.ZodNumber>;
|
|
3994
|
+
port: zod.ZodOptional<zod.ZodNumber>;
|
|
3995
|
+
lastPort: zod.ZodOptional<zod.ZodNumber>;
|
|
3996
|
+
connectPort: zod.ZodOptional<zod.ZodNumber>;
|
|
3997
|
+
lastConnectPort: zod.ZodOptional<zod.ZodNumber>;
|
|
3998
|
+
directPort: zod.ZodOptional<zod.ZodNumber>;
|
|
3999
|
+
lastDirectPort: zod.ZodOptional<zod.ZodNumber>;
|
|
4000
|
+
lastError: zod.ZodOptional<zod.ZodString>;
|
|
4001
|
+
}, zod_v4_core.$strict>;
|
|
4002
|
+
supervisorAlive: zod.ZodBoolean;
|
|
4003
|
+
sessions: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
4004
|
+
pid: zod.ZodInt;
|
|
4005
|
+
startedAt: zod.ZodNumber;
|
|
4006
|
+
alive: zod.ZodBoolean;
|
|
4007
|
+
}, zod_v4_core.$strict>>>;
|
|
4008
|
+
headroomSocket: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodObject<{
|
|
4009
|
+
socketPath: zod.ZodString;
|
|
4010
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4011
|
+
refused: zod.ZodString;
|
|
4012
|
+
}, zod_v4_core.$strict>]>>;
|
|
4013
|
+
logPath: zod.ZodString;
|
|
4014
|
+
logExists: zod.ZodBoolean;
|
|
4015
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
4016
|
+
sessions: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, Schema<unknown, unknown>, zod.ZodObject<{
|
|
4017
|
+
sessions: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
4018
|
+
pid: zod.ZodInt;
|
|
4019
|
+
startedAt: zod.ZodNumber;
|
|
4020
|
+
alive: zod.ZodBoolean;
|
|
4021
|
+
}, zod_v4_core.$strict>>>;
|
|
4022
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
4023
|
+
};
|
|
4024
|
+
check: {
|
|
4025
|
+
run: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
4026
|
+
path: zod.ZodString;
|
|
4027
|
+
identity: zod.ZodOptional<zod.ZodString>;
|
|
4028
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4029
|
+
identity: zod.ZodObject<{
|
|
4030
|
+
name: zod.ZodNullable<zod.ZodString>;
|
|
4031
|
+
source: zod.ZodEnum<{
|
|
4032
|
+
"config-dir-escape-hatch": "config-dir-escape-hatch";
|
|
4033
|
+
argv: "argv";
|
|
4034
|
+
env: "env";
|
|
4035
|
+
"directory-pin": "directory-pin";
|
|
4036
|
+
"active-identity-file": "active-identity-file";
|
|
4037
|
+
none: "none";
|
|
4038
|
+
}>;
|
|
4039
|
+
}, zod_v4_core.$strict>;
|
|
4040
|
+
pool: zod.ZodOptional<zod.ZodObject<{
|
|
4041
|
+
pool: zod.ZodString;
|
|
4042
|
+
directory: zod.ZodString;
|
|
4043
|
+
pick: zod.ZodOptional<zod.ZodString>;
|
|
4044
|
+
candidates: zod.ZodArray<zod.ZodObject<{
|
|
4045
|
+
identity: zod.ZodString;
|
|
4046
|
+
class: zod.ZodEnum<{
|
|
4047
|
+
unknown: "unknown";
|
|
4048
|
+
scored: "scored";
|
|
4049
|
+
"pay-per-use": "pay-per-use";
|
|
4050
|
+
ineligible: "ineligible";
|
|
4051
|
+
}>;
|
|
4052
|
+
score: zod.ZodOptional<zod.ZodNumber>;
|
|
4053
|
+
feasible: zod.ZodBoolean;
|
|
4054
|
+
blockedUntil: zod.ZodOptional<zod.ZodISODateTime>;
|
|
4055
|
+
plan: zod.ZodUnion<readonly [zod.ZodObject<{
|
|
4056
|
+
kind: zod.ZodLiteral<"subscription">;
|
|
4057
|
+
capacity: zod.ZodNumber;
|
|
4058
|
+
recognised: zod.ZodBoolean;
|
|
4059
|
+
tier: zod.ZodOptional<zod.ZodString>;
|
|
4060
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4061
|
+
kind: zod.ZodLiteral<"pay-per-use">;
|
|
4062
|
+
tier: zod.ZodOptional<zod.ZodString>;
|
|
4063
|
+
}, zod_v4_core.$strict>]>;
|
|
4064
|
+
reasons: zod.ZodArray<zod.ZodString>;
|
|
4065
|
+
}, zod_v4_core.$strict>>;
|
|
4066
|
+
missing: zod.ZodArray<zod.ZodString>;
|
|
4067
|
+
earliestReturn: zod.ZodOptional<zod.ZodObject<{
|
|
4068
|
+
identity: zod.ZodString;
|
|
4069
|
+
at: zod.ZodISODateTime;
|
|
4070
|
+
}, zod_v4_core.$strict>>;
|
|
4071
|
+
stickyProblem: zod.ZodOptional<zod.ZodString>;
|
|
4072
|
+
}, zod_v4_core.$strict>>;
|
|
4073
|
+
configProfile: zod.ZodObject<{
|
|
4074
|
+
name: zod.ZodNullable<zod.ZodString>;
|
|
4075
|
+
source: zod.ZodEnum<{
|
|
4076
|
+
"directory-rule": "directory-rule";
|
|
4077
|
+
env: "env";
|
|
4078
|
+
none: "none";
|
|
4079
|
+
"cli-flag": "cli-flag";
|
|
4080
|
+
"identity-default": "identity-default";
|
|
4081
|
+
"global-default": "global-default";
|
|
4082
|
+
}>;
|
|
4083
|
+
}, zod_v4_core.$strict>;
|
|
4084
|
+
layers: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
4085
|
+
id: zod.ZodInt;
|
|
4086
|
+
kind: zod.ZodEnum<{
|
|
4087
|
+
"global-config": "global-config";
|
|
4088
|
+
"config-profile": "config-profile";
|
|
4089
|
+
"directory-rule": "directory-rule";
|
|
4090
|
+
portable: "portable";
|
|
4091
|
+
"portable-local": "portable-local";
|
|
4092
|
+
"cli-override": "cli-override";
|
|
4093
|
+
}>;
|
|
4094
|
+
source: zod.ZodString;
|
|
4095
|
+
}, zod_v4_core.$strict>>>;
|
|
4096
|
+
entries: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
4097
|
+
path: zod.ZodString;
|
|
4098
|
+
shared: zod.ZodBoolean;
|
|
4099
|
+
via: zod.ZodEnum<{
|
|
4100
|
+
"secret-floor": "secret-floor";
|
|
4101
|
+
unclassified: "unclassified";
|
|
4102
|
+
"entry-rule": "entry-rule";
|
|
4103
|
+
"category-override": "category-override";
|
|
4104
|
+
"category-default": "category-default";
|
|
4105
|
+
}>;
|
|
4106
|
+
category: zod.ZodNullable<zod.ZodEnum<{
|
|
4107
|
+
secret: "secret";
|
|
4108
|
+
runtime: "runtime";
|
|
4109
|
+
history: "history";
|
|
4110
|
+
knowledge: "knowledge";
|
|
4111
|
+
settings: "settings";
|
|
4112
|
+
}>>;
|
|
4113
|
+
rule: zod.ZodOptional<zod.ZodObject<{
|
|
4114
|
+
key: zod.ZodString;
|
|
4115
|
+
layer: zod.ZodInt;
|
|
4116
|
+
}, zod_v4_core.$strict>>;
|
|
4117
|
+
eliminated: zod.ZodOptional<zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
4118
|
+
key: zod.ZodString;
|
|
4119
|
+
failed: zod.ZodReadonly<zod.ZodArray<zod.ZodString>>;
|
|
4120
|
+
}, zod_v4_core.$strict>>>>;
|
|
4121
|
+
}, zod_v4_core.$strict>>>;
|
|
4122
|
+
projectEncodingAmbiguities: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
4123
|
+
fragment: zod.ZodString;
|
|
4124
|
+
encoded: zod.ZodString;
|
|
4125
|
+
reason: zod.ZodEnum<{
|
|
4126
|
+
"lossy-characters": "lossy-characters";
|
|
4127
|
+
"collides-with-sibling-pattern": "collides-with-sibling-pattern";
|
|
4128
|
+
}>;
|
|
4129
|
+
detail: zod.ZodString;
|
|
4130
|
+
}, zod_v4_core.$strict>>>;
|
|
4131
|
+
diagnostics: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
4132
|
+
code: zod.ZodEnum<{
|
|
4133
|
+
EXTENDS_CYCLE: "EXTENDS_CYCLE";
|
|
4134
|
+
MISSING_PROFILE: "MISSING_PROFILE";
|
|
4135
|
+
SECRET_ENTRY_KEY: "SECRET_ENTRY_KEY";
|
|
4136
|
+
SECRET_PATH_NEUTRALISED: "SECRET_PATH_NEUTRALISED";
|
|
4137
|
+
CATEGORY_PREFIX_MISMATCH: "CATEGORY_PREFIX_MISMATCH";
|
|
4138
|
+
MALFORMED_ENTRY_KEY: "MALFORMED_ENTRY_KEY";
|
|
4139
|
+
EXACT_ENTRY_OVERRIDDEN_BY_LATER_GLOB: "EXACT_ENTRY_OVERRIDDEN_BY_LATER_GLOB";
|
|
4140
|
+
AMBIGUOUS_PROJECT_ENCODING: "AMBIGUOUS_PROJECT_ENCODING";
|
|
4141
|
+
UNROOTED_PROJECT_PATH: "UNROOTED_PROJECT_PATH";
|
|
4142
|
+
UNCLASSIFIED_ENTRY: "UNCLASSIFIED_ENTRY";
|
|
4143
|
+
EMPTY_WHEN: "EMPTY_WHEN";
|
|
4144
|
+
FARM_MANIFEST_MISSING: "FARM_MANIFEST_MISSING";
|
|
4145
|
+
RECONCILE_CONFLICT: "RECONCILE_CONFLICT";
|
|
4146
|
+
RECONCILE_SECRET_BLOCKED: "RECONCILE_SECRET_BLOCKED";
|
|
4147
|
+
FARM_SWAP_RECOVERED: "FARM_SWAP_RECOVERED";
|
|
4148
|
+
FARM_PREVIOUS_RETAINED: "FARM_PREVIOUS_RETAINED";
|
|
4149
|
+
}>;
|
|
4150
|
+
severity: zod.ZodEnum<{
|
|
4151
|
+
error: "error";
|
|
4152
|
+
warning: "warning";
|
|
4153
|
+
info: "info";
|
|
4154
|
+
}>;
|
|
4155
|
+
message: zod.ZodString;
|
|
4156
|
+
subject: zod.ZodOptional<zod.ZodString>;
|
|
4157
|
+
layer: zod.ZodOptional<zod.ZodInt>;
|
|
4158
|
+
}, zod_v4_core.$strict>>>;
|
|
4159
|
+
ambientCredential: zod.ZodUnion<readonly [zod.ZodObject<{
|
|
4160
|
+
ok: zod.ZodLiteral<true>;
|
|
4161
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4162
|
+
ok: zod.ZodLiteral<false>;
|
|
4163
|
+
variable: zod.ZodString;
|
|
4164
|
+
message: zod.ZodString;
|
|
4165
|
+
}, zod_v4_core.$strict>]>;
|
|
4166
|
+
keychain: zod.ZodOptional<zod.ZodObject<{
|
|
4167
|
+
checked: zod.ZodLiteral<true>;
|
|
4168
|
+
found: zod.ZodBoolean;
|
|
4169
|
+
serviceName: zod.ZodOptional<zod.ZodString>;
|
|
4170
|
+
note: zod.ZodString;
|
|
4171
|
+
}, zod_v4_core.$strict>>;
|
|
4172
|
+
settingsExposure: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
4173
|
+
file: zod.ZodString;
|
|
4174
|
+
envKeyNames: zod.ZodReadonly<zod.ZodArray<zod.ZodString>>;
|
|
4175
|
+
hookEventNames: zod.ZodReadonly<zod.ZodArray<zod.ZodString>>;
|
|
4176
|
+
hookCommandCount: zod.ZodInt;
|
|
4177
|
+
}, zod_v4_core.$strict>>>;
|
|
4178
|
+
credential: zod.ZodObject<{
|
|
4179
|
+
applies: zod.ZodEnum<{
|
|
4180
|
+
identity: "identity";
|
|
4181
|
+
provider: "provider";
|
|
4182
|
+
"stored-login": "stored-login";
|
|
4183
|
+
}>;
|
|
4184
|
+
provider: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodObject<{
|
|
4185
|
+
name: zod.ZodString;
|
|
4186
|
+
credential: zod.ZodObject<{
|
|
4187
|
+
target: zod.ZodEnum<{
|
|
4188
|
+
bearer: "bearer";
|
|
4189
|
+
apiKey: "apiKey";
|
|
4190
|
+
oauthToken: "oauthToken";
|
|
4191
|
+
}>;
|
|
4192
|
+
sources: zod.ZodReadonly<zod.ZodArray<zod.ZodUnion<readonly [zod.ZodObject<{
|
|
4193
|
+
kind: zod.ZodLiteral<"env">;
|
|
4194
|
+
variable: zod.ZodString;
|
|
4195
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4196
|
+
kind: zod.ZodLiteral<"file">;
|
|
4197
|
+
path: zod.ZodString;
|
|
4198
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4199
|
+
kind: zod.ZodLiteral<"command">;
|
|
4200
|
+
program: zod.ZodString;
|
|
4201
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4202
|
+
kind: zod.ZodLiteral<"op">;
|
|
4203
|
+
reference: zod.ZodString;
|
|
4204
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4205
|
+
kind: zod.ZodLiteral<"keychain">;
|
|
4206
|
+
service: zod.ZodString;
|
|
4207
|
+
account: zod.ZodOptional<zod.ZodString>;
|
|
4208
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4209
|
+
kind: zod.ZodLiteral<"literal">;
|
|
4210
|
+
}, zod_v4_core.$strict>]>>>;
|
|
4211
|
+
cache: zod.ZodOptional<zod.ZodObject<{
|
|
4212
|
+
ttl: zod.ZodOptional<zod.ZodString>;
|
|
4213
|
+
store: zod.ZodOptional<zod.ZodEnum<{
|
|
4214
|
+
file: "file";
|
|
4215
|
+
keychain: "keychain";
|
|
4216
|
+
}>>;
|
|
4217
|
+
}, zod_v4_core.$strict>>;
|
|
4218
|
+
}, zod_v4_core.$strict>;
|
|
4219
|
+
cached: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodObject<{
|
|
4220
|
+
store: zod.ZodEnum<{
|
|
4221
|
+
file: "file";
|
|
4222
|
+
keychain: "keychain";
|
|
4223
|
+
}>;
|
|
4224
|
+
status: zod.ZodLiteral<"empty">;
|
|
4225
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4226
|
+
store: zod.ZodEnum<{
|
|
4227
|
+
file: "file";
|
|
4228
|
+
keychain: "keychain";
|
|
4229
|
+
}>;
|
|
4230
|
+
status: zod.ZodLiteral<"unreadable">;
|
|
4231
|
+
reason: zod.ZodString;
|
|
4232
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4233
|
+
store: zod.ZodEnum<{
|
|
4234
|
+
file: "file";
|
|
4235
|
+
keychain: "keychain";
|
|
4236
|
+
}>;
|
|
4237
|
+
status: zod.ZodEnum<{
|
|
4238
|
+
fresh: "fresh";
|
|
4239
|
+
expired: "expired";
|
|
4240
|
+
}>;
|
|
4241
|
+
ageMs: zod.ZodNumber;
|
|
4242
|
+
expiresInMs: zod.ZodOptional<zod.ZodNumber>;
|
|
4243
|
+
}, zod_v4_core.$strict>]>>;
|
|
4244
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4245
|
+
name: zod.ZodString;
|
|
4246
|
+
problem: zod.ZodString;
|
|
4247
|
+
}, zod_v4_core.$strict>]>>;
|
|
4248
|
+
identity: zod.ZodOptional<zod.ZodObject<{
|
|
4249
|
+
target: zod.ZodEnum<{
|
|
4250
|
+
bearer: "bearer";
|
|
4251
|
+
apiKey: "apiKey";
|
|
4252
|
+
oauthToken: "oauthToken";
|
|
4253
|
+
}>;
|
|
4254
|
+
sources: zod.ZodReadonly<zod.ZodArray<zod.ZodUnion<readonly [zod.ZodObject<{
|
|
4255
|
+
kind: zod.ZodLiteral<"env">;
|
|
4256
|
+
variable: zod.ZodString;
|
|
4257
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4258
|
+
kind: zod.ZodLiteral<"file">;
|
|
4259
|
+
path: zod.ZodString;
|
|
4260
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4261
|
+
kind: zod.ZodLiteral<"command">;
|
|
4262
|
+
program: zod.ZodString;
|
|
4263
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4264
|
+
kind: zod.ZodLiteral<"op">;
|
|
4265
|
+
reference: zod.ZodString;
|
|
4266
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4267
|
+
kind: zod.ZodLiteral<"keychain">;
|
|
4268
|
+
service: zod.ZodString;
|
|
4269
|
+
account: zod.ZodOptional<zod.ZodString>;
|
|
4270
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4271
|
+
kind: zod.ZodLiteral<"literal">;
|
|
4272
|
+
}, zod_v4_core.$strict>]>>>;
|
|
4273
|
+
cache: zod.ZodOptional<zod.ZodObject<{
|
|
4274
|
+
ttl: zod.ZodOptional<zod.ZodString>;
|
|
4275
|
+
store: zod.ZodOptional<zod.ZodEnum<{
|
|
4276
|
+
file: "file";
|
|
4277
|
+
keychain: "keychain";
|
|
4278
|
+
}>>;
|
|
4279
|
+
}, zod_v4_core.$strict>>;
|
|
4280
|
+
}, zod_v4_core.$strict>>;
|
|
4281
|
+
identityCached: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodObject<{
|
|
4282
|
+
store: zod.ZodEnum<{
|
|
4283
|
+
file: "file";
|
|
4284
|
+
keychain: "keychain";
|
|
4285
|
+
}>;
|
|
4286
|
+
status: zod.ZodLiteral<"empty">;
|
|
4287
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4288
|
+
store: zod.ZodEnum<{
|
|
4289
|
+
file: "file";
|
|
4290
|
+
keychain: "keychain";
|
|
4291
|
+
}>;
|
|
4292
|
+
status: zod.ZodLiteral<"unreadable">;
|
|
4293
|
+
reason: zod.ZodString;
|
|
4294
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4295
|
+
store: zod.ZodEnum<{
|
|
4296
|
+
file: "file";
|
|
4297
|
+
keychain: "keychain";
|
|
4298
|
+
}>;
|
|
4299
|
+
status: zod.ZodEnum<{
|
|
4300
|
+
fresh: "fresh";
|
|
4301
|
+
expired: "expired";
|
|
4302
|
+
}>;
|
|
4303
|
+
ageMs: zod.ZodNumber;
|
|
4304
|
+
expiresInMs: zod.ZodOptional<zod.ZodNumber>;
|
|
4305
|
+
}, zod_v4_core.$strict>]>>;
|
|
4306
|
+
}, zod_v4_core.$strict>;
|
|
4307
|
+
claudeVersion: zod.ZodOptional<zod.ZodObject<{
|
|
4308
|
+
pinned: zod.ZodOptional<zod.ZodObject<{
|
|
4309
|
+
version: zod.ZodString;
|
|
4310
|
+
source: zod.ZodEnum<{
|
|
4311
|
+
flag: "flag";
|
|
4312
|
+
environment: "environment";
|
|
4313
|
+
cascade: "cascade";
|
|
4314
|
+
}>;
|
|
4315
|
+
installed: zod.ZodBoolean;
|
|
4316
|
+
}, zod_v4_core.$strict>>;
|
|
4317
|
+
highestInstalled: zod.ZodOptional<zod.ZodString>;
|
|
4318
|
+
installed: zod.ZodReadonly<zod.ZodArray<zod.ZodString>>;
|
|
4319
|
+
}, zod_v4_core.$strict>>;
|
|
4320
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
4321
|
+
};
|
|
4322
|
+
doctor: {
|
|
4323
|
+
run: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, Schema<unknown, unknown>, zod.ZodObject<{
|
|
4324
|
+
ok: zod.ZodBoolean;
|
|
4325
|
+
findings: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
4326
|
+
section: zod.ZodEnum<{
|
|
4327
|
+
"global-config": "global-config";
|
|
4328
|
+
"config-profile": "config-profile";
|
|
4329
|
+
identity: "identity";
|
|
4330
|
+
provider: "provider";
|
|
4331
|
+
pool: "pool";
|
|
4332
|
+
keychain: "keychain";
|
|
4333
|
+
"ambient-credential": "ambient-credential";
|
|
4334
|
+
"binary-discovery": "binary-discovery";
|
|
4335
|
+
"claude-shim": "claude-shim";
|
|
4336
|
+
"path-resolution": "path-resolution";
|
|
4337
|
+
"legacy-name": "legacy-name";
|
|
4338
|
+
"directory-rules": "directory-rules";
|
|
4339
|
+
"categories-local": "categories-local";
|
|
4340
|
+
"active-identity": "active-identity";
|
|
4341
|
+
headroom: "headroom";
|
|
4342
|
+
}>;
|
|
4343
|
+
subject: zod.ZodOptional<zod.ZodString>;
|
|
4344
|
+
severity: zod.ZodEnum<{
|
|
4345
|
+
pass: "pass";
|
|
4346
|
+
warn: "warn";
|
|
4347
|
+
fail: "fail";
|
|
4348
|
+
}>;
|
|
4349
|
+
message: zod.ZodString;
|
|
4350
|
+
}, zod_v4_core.$strict>>>;
|
|
4351
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
4352
|
+
};
|
|
4353
|
+
rc: {
|
|
4354
|
+
list: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, Schema<unknown, unknown>, zod.ZodObject<{
|
|
4355
|
+
sessions: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
4356
|
+
id: zod.ZodString;
|
|
4357
|
+
createdAt: zod.ZodNumber;
|
|
4358
|
+
lastSeenAt: zod.ZodNumber;
|
|
4359
|
+
}, zod_v4_core.$strict>>>;
|
|
4360
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
4361
|
+
status: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
4362
|
+
session: zod.ZodOptional<zod.ZodString>;
|
|
4363
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4364
|
+
statuses: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
4365
|
+
workerState: zod.ZodOptional<zod.ZodObject<{
|
|
4366
|
+
value: zod.ZodString;
|
|
4367
|
+
observedAt: zod.ZodNumber;
|
|
4368
|
+
}, zod_v4_core.$strict>>;
|
|
4369
|
+
workerIdleSeconds: zod.ZodOptional<zod.ZodObject<{
|
|
4370
|
+
value: zod.ZodNumber;
|
|
4371
|
+
observedAt: zod.ZodNumber;
|
|
4372
|
+
}, zod_v4_core.$strict>>;
|
|
4373
|
+
pending: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
4374
|
+
sessionId: zod.ZodString;
|
|
4375
|
+
requestId: zod.ZodString;
|
|
4376
|
+
type: zod.ZodString;
|
|
4377
|
+
summary: zod.ZodString;
|
|
4378
|
+
observedAt: zod.ZodNumber;
|
|
4379
|
+
}, zod_v4_core.$strict>>>;
|
|
4380
|
+
id: zod.ZodString;
|
|
4381
|
+
createdAt: zod.ZodNumber;
|
|
4382
|
+
lastSeenAt: zod.ZodNumber;
|
|
4383
|
+
}, zod_v4_core.$strict>>>;
|
|
4384
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
4385
|
+
pending: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
4386
|
+
session: zod.ZodOptional<zod.ZodString>;
|
|
4387
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4388
|
+
pending: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
|
4389
|
+
sessionId: zod.ZodString;
|
|
4390
|
+
requestId: zod.ZodString;
|
|
4391
|
+
type: zod.ZodString;
|
|
4392
|
+
summary: zod.ZodString;
|
|
4393
|
+
observedAt: zod.ZodNumber;
|
|
4394
|
+
}, zod_v4_core.$strict>>>;
|
|
4395
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
4396
|
+
send: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
4397
|
+
session: zod.ZodString;
|
|
4398
|
+
text: zod.ZodString;
|
|
4399
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4400
|
+
session: zod.ZodString;
|
|
4401
|
+
sequenceNums: zod.ZodReadonly<zod.ZodArray<zod.ZodNumber>>;
|
|
4402
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
4403
|
+
answer: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
4404
|
+
session: zod.ZodString;
|
|
4405
|
+
request: zod.ZodString;
|
|
4406
|
+
approve: zod.ZodBoolean;
|
|
4407
|
+
text: zod.ZodOptional<zod.ZodString>;
|
|
4408
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4409
|
+
session: zod.ZodString;
|
|
4410
|
+
request: zod.ZodString;
|
|
4411
|
+
sequenceNums: zod.ZodReadonly<zod.ZodArray<zod.ZodNumber>>;
|
|
4412
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
4413
|
+
interrupt: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
4414
|
+
session: zod.ZodString;
|
|
4415
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4416
|
+
session: zod.ZodString;
|
|
4417
|
+
sequenceNums: zod.ZodReadonly<zod.ZodArray<zod.ZodNumber>>;
|
|
4418
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
4419
|
+
setModel: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
4420
|
+
session: zod.ZodString;
|
|
4421
|
+
model: zod.ZodString;
|
|
4422
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4423
|
+
session: zod.ZodString;
|
|
4424
|
+
sequenceNums: zod.ZodReadonly<zod.ZodArray<zod.ZodNumber>>;
|
|
4425
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
4426
|
+
setPermissionMode: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
4427
|
+
session: zod.ZodString;
|
|
4428
|
+
mode: zod.ZodEnum<{
|
|
4429
|
+
default: "default";
|
|
4430
|
+
acceptEdits: "acceptEdits";
|
|
4431
|
+
bypassPermissions: "bypassPermissions";
|
|
4432
|
+
plan: "plan";
|
|
4433
|
+
dontAsk: "dontAsk";
|
|
4434
|
+
auto: "auto";
|
|
4435
|
+
}>;
|
|
4436
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4437
|
+
session: zod.ZodString;
|
|
4438
|
+
sequenceNums: zod.ZodReadonly<zod.ZodArray<zod.ZodNumber>>;
|
|
4439
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
4440
|
+
subscribe: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
4441
|
+
session: zod.ZodOptional<zod.ZodString>;
|
|
4442
|
+
}, zod_v4_core.$strict>, any, Record<never, never>, Record<never, never>>;
|
|
4443
|
+
};
|
|
4444
|
+
};
|
|
4445
|
+
/** The door's whole typed API, as the client the door's own verbs and library consumers use is derived from it. */
|
|
4446
|
+
type DoorApiRouter = ReturnType<typeof createDoorApiRouter>;
|
|
4447
|
+
/**
|
|
4448
|
+
* Builds the node handler for the door's whole typed API, Remote Control and control plane together: the pre-pipeline surface the provider listener hands every request under `RC_ORPC_PATH_PREFIX`.
|
|
4449
|
+
*/
|
|
4450
|
+
declare function createDoorApiNodeHandler(deps: DoorApiDeps): PrePipelineApi;
|
|
4451
|
+
/** The door's whole typed API as a client sees it: every call presents the control token, over TLS trusting only the CA file the door's own state names. */
|
|
4452
|
+
type DoorApiClient = RouterClient<DoorApiRouter>;
|
|
4453
|
+
/** Builds the client for the door's whole typed API: the same address, CA and per-generation control token the Remote Control client uses, with the control-plane procedures beside `rc.*`. */
|
|
4454
|
+
declare function frontDoorApiClient(port: number, ca: string, token: string): DoorApiClient;
|
|
4455
|
+
|
|
4456
|
+
/**
|
|
4457
|
+
* The Zod schemas of the door's general control plane: the usage snapshots a remote consumer reads, the front door's own status and session registry, the check report over a path, and the doctor report, each one the input or output of a procedure in `controlApi.ts`. Like `rcSchemas.ts` this module is a plain Zod leaf (nothing here imports oRPC), and every shape it asserts is one the implementation already defines: the usage snapshot and front-door state schemas are the store's and the registry's own, the check report's is `checkReportSchema.ts`'s (`CheckReportJsonSchema`, imported straight by the procedure), and the doctor vocabulary is `doctorReport.ts`'s own, so contract and behaviour share one source and a drift fails the procedures' own validation rather than shipping silently.
|
|
4458
|
+
*/
|
|
4459
|
+
/** Every usage snapshot on this machine, one per identity that has routed a request through the door. */
|
|
4460
|
+
declare const UsageListOutputSchema: z.ZodObject<{
|
|
4461
|
+
snapshots: z.ZodReadonly<z.ZodArray<z.ZodObject<{
|
|
4462
|
+
schemaVersion: z.ZodLiteral<1>;
|
|
4463
|
+
identity: z.ZodString;
|
|
4464
|
+
updatedAt: z.ZodISODateTime;
|
|
4465
|
+
account: z.ZodOptional<z.ZodObject<{
|
|
4466
|
+
accountUuid: z.ZodOptional<z.ZodString>;
|
|
4467
|
+
emailAddress: z.ZodOptional<z.ZodString>;
|
|
4468
|
+
displayName: z.ZodOptional<z.ZodString>;
|
|
4469
|
+
organizationUuid: z.ZodOptional<z.ZodString>;
|
|
4470
|
+
organizationName: z.ZodOptional<z.ZodString>;
|
|
4471
|
+
organizationType: z.ZodOptional<z.ZodString>;
|
|
4472
|
+
organizationRole: z.ZodOptional<z.ZodString>;
|
|
4473
|
+
workspaceRole: z.ZodOptional<z.ZodString>;
|
|
4474
|
+
billingType: z.ZodOptional<z.ZodString>;
|
|
4475
|
+
seatTier: z.ZodOptional<z.ZodString>;
|
|
4476
|
+
organizationRateLimitTier: z.ZodOptional<z.ZodString>;
|
|
4477
|
+
userRateLimitTier: z.ZodOptional<z.ZodString>;
|
|
4478
|
+
hasExtraUsageEnabled: z.ZodOptional<z.ZodBoolean>;
|
|
4479
|
+
subscriptionCreatedAt: z.ZodOptional<z.ZodString>;
|
|
4480
|
+
accountCreatedAt: z.ZodOptional<z.ZodString>;
|
|
4481
|
+
}, z.core.$strict>>;
|
|
4482
|
+
providers: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
4483
|
+
lastRequestAt: z.ZodISODateTime;
|
|
4484
|
+
lastStatus: z.ZodNumber;
|
|
4485
|
+
lastModel: z.ZodOptional<z.ZodString>;
|
|
4486
|
+
rateLimit: z.ZodOptional<z.ZodObject<{
|
|
4487
|
+
observedAt: z.ZodISODateTime;
|
|
4488
|
+
headers: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
4489
|
+
unified: z.ZodOptional<z.ZodObject<{
|
|
4490
|
+
status: z.ZodOptional<z.ZodString>;
|
|
4491
|
+
fiveHour: z.ZodOptional<z.ZodObject<{
|
|
4492
|
+
utilization: z.ZodOptional<z.ZodNumber>;
|
|
4493
|
+
resetsAt: z.ZodOptional<z.ZodISODateTime>;
|
|
4494
|
+
status: z.ZodOptional<z.ZodString>;
|
|
4495
|
+
}, z.core.$strict>>;
|
|
4496
|
+
sevenDay: z.ZodOptional<z.ZodObject<{
|
|
4497
|
+
utilization: z.ZodOptional<z.ZodNumber>;
|
|
4498
|
+
resetsAt: z.ZodOptional<z.ZodISODateTime>;
|
|
4499
|
+
status: z.ZodOptional<z.ZodString>;
|
|
4500
|
+
}, z.core.$strict>>;
|
|
4501
|
+
representativeClaim: z.ZodOptional<z.ZodString>;
|
|
4502
|
+
resetAt: z.ZodOptional<z.ZodISODateTime>;
|
|
4503
|
+
overageStatus: z.ZodOptional<z.ZodString>;
|
|
4504
|
+
}, z.core.$strict>>;
|
|
4505
|
+
}, z.core.$strict>>;
|
|
4506
|
+
lastLimit: z.ZodOptional<z.ZodObject<{
|
|
4507
|
+
kind: z.ZodEnum<{
|
|
4508
|
+
"rate-limited": "rate-limited";
|
|
4509
|
+
"quota-exhausted": "quota-exhausted";
|
|
4510
|
+
}>;
|
|
4511
|
+
retryAfterSeconds: z.ZodOptional<z.ZodNumber>;
|
|
4512
|
+
resetAt: z.ZodOptional<z.ZodISODateTime>;
|
|
4513
|
+
window: z.ZodOptional<z.ZodString>;
|
|
4514
|
+
evidence: z.ZodArray<z.ZodString>;
|
|
4515
|
+
observedAt: z.ZodISODateTime;
|
|
4516
|
+
status: z.ZodNumber;
|
|
4517
|
+
}, z.core.$strict>>;
|
|
4518
|
+
quota: z.ZodOptional<z.ZodObject<{
|
|
4519
|
+
observedAt: z.ZodISODateTime;
|
|
4520
|
+
source: z.ZodString;
|
|
4521
|
+
level: z.ZodOptional<z.ZodString>;
|
|
4522
|
+
windows: z.ZodArray<z.ZodObject<{
|
|
4523
|
+
measures: z.ZodString;
|
|
4524
|
+
periodMs: z.ZodOptional<z.ZodNumber>;
|
|
4525
|
+
period: z.ZodOptional<z.ZodString>;
|
|
4526
|
+
utilization: z.ZodNumber;
|
|
4527
|
+
resetsAt: z.ZodOptional<z.ZodISODateTime>;
|
|
4528
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
4529
|
+
used: z.ZodOptional<z.ZodNumber>;
|
|
4530
|
+
remaining: z.ZodOptional<z.ZodNumber>;
|
|
4531
|
+
}, z.core.$strict>>;
|
|
4532
|
+
}, z.core.$strict>>;
|
|
4533
|
+
}, z.core.$strict>>;
|
|
4534
|
+
}, z.core.$strict>>>;
|
|
4535
|
+
}, z.core.$strict>;
|
|
4536
|
+
/** The windows query: one identity by name, and optionally the provider whose windows are wanted (`anthropic` for an OAuth session, the default). */
|
|
4537
|
+
declare const UsageWindowsInputSchema: z.ZodObject<{
|
|
4538
|
+
identity: z.ZodString;
|
|
4539
|
+
provider: z.ZodOptional<z.ZodString>;
|
|
4540
|
+
}, z.core.$strict>;
|
|
4541
|
+
/** One quota window as it stands now, exactly as `effectiveWindow` reads a recorded one: a window whose reset has passed is empty and carries no status, so every consumer agrees on what an old observation still means. */
|
|
4542
|
+
declare const EffectiveWindowSchema: z.ZodObject<{
|
|
4543
|
+
reset: z.ZodBoolean;
|
|
4544
|
+
utilization: z.ZodOptional<z.ZodNumber>;
|
|
4545
|
+
resetsAtMs: z.ZodOptional<z.ZodNumber>;
|
|
4546
|
+
status: z.ZodOptional<z.ZodString>;
|
|
4547
|
+
}, z.core.$strict>;
|
|
4548
|
+
/** One identity's effective windows for a provider: what the snapshot last observed, read at the door's own clock. Absent fields mean the snapshot observed nothing there. */
|
|
4549
|
+
declare const UsageWindowsOutputSchema: z.ZodObject<{
|
|
4550
|
+
identity: z.ZodString;
|
|
4551
|
+
provider: z.ZodString;
|
|
4552
|
+
observedAt: z.ZodOptional<z.ZodISODateTime>;
|
|
4553
|
+
fiveHour: z.ZodOptional<z.ZodObject<{
|
|
4554
|
+
reset: z.ZodBoolean;
|
|
4555
|
+
utilization: z.ZodOptional<z.ZodNumber>;
|
|
4556
|
+
resetsAtMs: z.ZodOptional<z.ZodNumber>;
|
|
4557
|
+
status: z.ZodOptional<z.ZodString>;
|
|
4558
|
+
}, z.core.$strict>>;
|
|
4559
|
+
sevenDay: z.ZodOptional<z.ZodObject<{
|
|
4560
|
+
reset: z.ZodBoolean;
|
|
4561
|
+
utilization: z.ZodOptional<z.ZodNumber>;
|
|
4562
|
+
resetsAtMs: z.ZodOptional<z.ZodNumber>;
|
|
4563
|
+
status: z.ZodOptional<z.ZodString>;
|
|
4564
|
+
}, z.core.$strict>>;
|
|
4565
|
+
}, z.core.$strict>;
|
|
4566
|
+
/** One registered launch as the status surfaces list it: the launcher's pid and start time plus whether it is still running, never the session's capability token. */
|
|
4567
|
+
declare const FrontDoorSessionStatusSchema: z.ZodObject<{
|
|
4568
|
+
pid: z.ZodInt;
|
|
4569
|
+
startedAt: z.ZodNumber;
|
|
4570
|
+
alive: z.ZodBoolean;
|
|
4571
|
+
}, z.core.$strict>;
|
|
4572
|
+
/** The headroom daemon's socket as the door's hop reads it: the path it may dial, or the reason it must not. The two never appear together. */
|
|
4573
|
+
declare const HeadroomSocketTargetSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
4574
|
+
socketPath: z.ZodString;
|
|
4575
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
4576
|
+
refused: z.ZodString;
|
|
4577
|
+
}, z.core.$strict>]>;
|
|
4578
|
+
/** Everything the door's status procedure returns: the supervisor state file's own record, its liveness, the registered launches, the headroom hop, and the door's log. */
|
|
4579
|
+
declare const FrontDoorStatusOutputSchema: z.ZodObject<{
|
|
4580
|
+
state: z.ZodObject<{
|
|
4581
|
+
protocol: z.ZodOptional<z.ZodNumber>;
|
|
4582
|
+
supervisorPid: z.ZodOptional<z.ZodNumber>;
|
|
4583
|
+
port: z.ZodOptional<z.ZodNumber>;
|
|
4584
|
+
lastPort: z.ZodOptional<z.ZodNumber>;
|
|
4585
|
+
connectPort: z.ZodOptional<z.ZodNumber>;
|
|
4586
|
+
lastConnectPort: z.ZodOptional<z.ZodNumber>;
|
|
4587
|
+
directPort: z.ZodOptional<z.ZodNumber>;
|
|
4588
|
+
lastDirectPort: z.ZodOptional<z.ZodNumber>;
|
|
4589
|
+
lastError: z.ZodOptional<z.ZodString>;
|
|
4590
|
+
}, z.core.$strict>;
|
|
4591
|
+
supervisorAlive: z.ZodBoolean;
|
|
4592
|
+
sessions: z.ZodReadonly<z.ZodArray<z.ZodObject<{
|
|
4593
|
+
pid: z.ZodInt;
|
|
4594
|
+
startedAt: z.ZodNumber;
|
|
4595
|
+
alive: z.ZodBoolean;
|
|
4596
|
+
}, z.core.$strict>>>;
|
|
4597
|
+
headroomSocket: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
4598
|
+
socketPath: z.ZodString;
|
|
4599
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
4600
|
+
refused: z.ZodString;
|
|
4601
|
+
}, z.core.$strict>]>>;
|
|
4602
|
+
logPath: z.ZodString;
|
|
4603
|
+
logExists: z.ZodBoolean;
|
|
4604
|
+
}, z.core.$strict>;
|
|
4605
|
+
/** The session registry's live launches, as the door's sessions procedure returns them. */
|
|
4606
|
+
declare const FrontDoorSessionsOutputSchema: z.ZodObject<{
|
|
4607
|
+
sessions: z.ZodReadonly<z.ZodArray<z.ZodObject<{
|
|
4608
|
+
pid: z.ZodInt;
|
|
4609
|
+
startedAt: z.ZodNumber;
|
|
4610
|
+
alive: z.ZodBoolean;
|
|
4611
|
+
}, z.core.$strict>>>;
|
|
4612
|
+
}, z.core.$strict>;
|
|
4613
|
+
/** The check query: one absolute directory (the door has no working directory of the caller's to resolve a relative path against, so a relative one is refused rather than silently resolved somewhere else), and optionally the identity to check as `--identity` names it. */
|
|
4614
|
+
declare const CheckRunInputSchema: z.ZodObject<{
|
|
4615
|
+
path: z.ZodString;
|
|
4616
|
+
identity: z.ZodOptional<z.ZodString>;
|
|
4617
|
+
}, z.core.$strict>;
|
|
4618
|
+
/** One line of the doctor report: the section it belongs to, its severity, its message, and the identity/profile/rule it is about when there is one. */
|
|
4619
|
+
declare const DoctorFindingSchema: z.ZodObject<{
|
|
4620
|
+
section: z.ZodEnum<{
|
|
4621
|
+
"global-config": "global-config";
|
|
4622
|
+
"config-profile": "config-profile";
|
|
4623
|
+
identity: "identity";
|
|
4624
|
+
provider: "provider";
|
|
4625
|
+
pool: "pool";
|
|
4626
|
+
keychain: "keychain";
|
|
4627
|
+
"ambient-credential": "ambient-credential";
|
|
4628
|
+
"binary-discovery": "binary-discovery";
|
|
4629
|
+
"claude-shim": "claude-shim";
|
|
4630
|
+
"path-resolution": "path-resolution";
|
|
4631
|
+
"legacy-name": "legacy-name";
|
|
4632
|
+
"directory-rules": "directory-rules";
|
|
4633
|
+
"categories-local": "categories-local";
|
|
4634
|
+
"active-identity": "active-identity";
|
|
4635
|
+
headroom: "headroom";
|
|
4636
|
+
}>;
|
|
4637
|
+
subject: z.ZodOptional<z.ZodString>;
|
|
4638
|
+
severity: z.ZodEnum<{
|
|
4639
|
+
pass: "pass";
|
|
4640
|
+
warn: "warn";
|
|
4641
|
+
fail: "fail";
|
|
4642
|
+
}>;
|
|
4643
|
+
message: z.ZodString;
|
|
4644
|
+
}, z.core.$strict>;
|
|
4645
|
+
/** The doctor report as data: every finding and whether any of them failed. */
|
|
4646
|
+
declare const DoctorRunOutputSchema: z.ZodObject<{
|
|
4647
|
+
ok: z.ZodBoolean;
|
|
4648
|
+
findings: z.ZodReadonly<z.ZodArray<z.ZodObject<{
|
|
4649
|
+
section: z.ZodEnum<{
|
|
4650
|
+
"global-config": "global-config";
|
|
4651
|
+
"config-profile": "config-profile";
|
|
4652
|
+
identity: "identity";
|
|
4653
|
+
provider: "provider";
|
|
4654
|
+
pool: "pool";
|
|
4655
|
+
keychain: "keychain";
|
|
4656
|
+
"ambient-credential": "ambient-credential";
|
|
4657
|
+
"binary-discovery": "binary-discovery";
|
|
4658
|
+
"claude-shim": "claude-shim";
|
|
4659
|
+
"path-resolution": "path-resolution";
|
|
4660
|
+
"legacy-name": "legacy-name";
|
|
4661
|
+
"directory-rules": "directory-rules";
|
|
4662
|
+
"categories-local": "categories-local";
|
|
4663
|
+
"active-identity": "active-identity";
|
|
4664
|
+
headroom: "headroom";
|
|
4665
|
+
}>;
|
|
4666
|
+
subject: z.ZodOptional<z.ZodString>;
|
|
4667
|
+
severity: z.ZodEnum<{
|
|
4668
|
+
pass: "pass";
|
|
4669
|
+
warn: "warn";
|
|
4670
|
+
fail: "fail";
|
|
4671
|
+
}>;
|
|
4672
|
+
message: z.ZodString;
|
|
4673
|
+
}, z.core.$strict>>>;
|
|
4674
|
+
}, z.core.$strict>;
|
|
2756
4675
|
|
|
2757
4676
|
/**
|
|
2758
|
-
* The
|
|
4677
|
+
* The self-hosted Remote Control service: the door serving, locally, the CCR surface it normally only observes (ExaDev/agent-shim#207). When the mode is on, a Claude Code session activates Remote Control against this surface and is controlled through it with no Anthropic credential anywhere: the door answers the session family itself instead of piping it to the real API host, so the `cse_` sessions, their sequence numbers, their worker and client streams and their event writes all live on this machine.
|
|
4678
|
+
*
|
|
4679
|
+
* The protocol spoken is exactly the one the door already speaks as a client, which is what makes this honest: every path, envelope, sequence rule and resume pair below is the shape the merged client-half machinery (`rcSessions.ts`, `rcStream.ts`, `connectEffects.ts`) dials the real host with, cross-checked against the CLI source (the 2.1.88 source-map dump behind the issue's spike) and live 2.1.289 envelopes captured through the interception rig. The transport is version-unstable (CCRv1 websocket to CCRv2 SSE plus POST within the 2.1.x line), so this surface pins what the rig's pinned CLI speaks and must be re-verified on upgrades; that standing caveat is issue #207's own.
|
|
4680
|
+
*
|
|
4681
|
+
* Division of the surface: the session family (`/v1/code/sessions...` and the `/v1/sessions` compatibility list) rides the routed pipeline as a `FrontDoorRoute`, so it flows through the same admission and middleware as any routed request and, above all, through the same observation wrapper that feeds the tracker (the door's own client half learns each session's credential precisely because the create is observed like any other exchange). The non-`/v1/` answers the CLI needs around activation (feature eval, profile, telemetry no-ops) and the OAuth refresh on the control-plane host have no pipeline to ride, so they are served by `local`, which the connect surface consults before routing or piping; that surface also takes over the control-plane host's terminated session as ordinary HTTP (it is normally byte-tapped) because answering `/v1/oauth/token` requires parsing it.
|
|
4682
|
+
*
|
|
4683
|
+
* The one network lever this uses is the bridge response's `api_base_url`: the protocol lets the server name where the worker dials, so the door names the API host it itself terminates, and the worker's `/worker/...` calls arrive straight back at this surface over the same interception that carried the create.
|
|
4684
|
+
*
|
|
4685
|
+
* Everything is in memory only and dies with the door process: sessions, events, worker JWTs. No credential this door authenticates against is ever written or logged by this module; the minting command owns the files.
|
|
2759
4686
|
*/
|
|
2760
|
-
/** The
|
|
2761
|
-
|
|
2762
|
-
/**
|
|
2763
|
-
declare
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
}
|
|
2767
|
-
/** The path of an identity's snapshot. Throws for an invalid identity name, which could otherwise name a path outside the snapshots directory. */
|
|
2768
|
-
declare function snapshotPath(snapshotsDir: string, identity: string): string;
|
|
2769
|
-
/** Reads one identity's snapshot: undefined when it has none yet, `UsageSnapshotError` when the file is there but unreadable. */
|
|
2770
|
-
declare function readUsageSnapshot(fs: Pick<FarmFs, "readFileUtf8">, snapshotsDir: string, identity: string): UsageSnapshot | undefined;
|
|
2771
|
-
/** Reads every identity's snapshot, by identity name. */
|
|
2772
|
-
declare function listUsageSnapshots(fs: UsageReadFs, snapshotsDir: string): readonly UsageSnapshot[];
|
|
2773
|
-
|
|
2774
|
-
/** A quota window as it stands at a given instant. */
|
|
2775
|
-
interface EffectiveWindow {
|
|
2776
|
-
/** True when the window's reset time has passed, so the recorded observation describes a window that no longer exists. */
|
|
2777
|
-
readonly reset: boolean;
|
|
2778
|
-
/** The fraction used: 0 for a reset window, otherwise what was last observed (a lower bound, since utilisation only rises within a window), or undefined when none was reported. */
|
|
2779
|
-
readonly utilization?: number;
|
|
2780
|
-
/** The reset instant, for a window that has not reset yet and reported one. */
|
|
2781
|
-
readonly resetsAtMs?: number;
|
|
2782
|
-
/** The window's own status, for a window that has not reset yet. */
|
|
2783
|
-
readonly status?: string;
|
|
2784
|
-
}
|
|
2785
|
-
/** Reads a recorded window at `nowMs`: a window whose reset has passed is empty and carries no status, so every consumer agrees on what an old observation still means. */
|
|
2786
|
-
declare function effectiveWindow(window: Readonly<QuotaWindow>, nowMs: number): EffectiveWindow;
|
|
2787
|
-
|
|
4687
|
+
/** The environment variable that turns the self-hosted Remote Control service on, read once at door start like the door's other mode selections: the door is one process serving every launch, so the mode is a property of the door, not of any one launch. Anything but `1` means off, the same exact-value vocabulary the capture toggle uses. */
|
|
4688
|
+
declare const RC_SELF_HOST_ENV = "AGENT_SHIM_FRONTDOOR_RC_SELF_HOST";
|
|
4689
|
+
/** Whether the environment asked for the self-hosted Remote Control service. */
|
|
4690
|
+
declare function rcSelfHostFromEnv(env: NodeJS.ProcessEnv): boolean;
|
|
4691
|
+
/** The full scope list the minting writes and the local refresh echoes: the CLI's own claude.ai login scope set (`CLAUDE_AI_OAUTH_SCOPES` in its source), whose `user:inference` and `user:profile` members are exactly the two the Remote Control gate demands. */
|
|
4692
|
+
declare const RC_SELF_HOST_SCOPE_LIST: readonly string[];
|
|
2788
4693
|
/**
|
|
2789
|
-
*
|
|
4694
|
+
* How long a minted worker JWT is good for. Not a fresh number: 46800 seconds is the `expires_in` the real bridge handed the live rig session (13 hours), so the local surface keeps the CLI's refresh cadence exactly where the real one put it.
|
|
2790
4695
|
*/
|
|
2791
|
-
declare const
|
|
2792
|
-
kind: z.ZodLiteral<"subscription">;
|
|
2793
|
-
capacity: z.ZodNumber;
|
|
2794
|
-
recognised: z.ZodBoolean;
|
|
2795
|
-
tier: z.ZodOptional<z.ZodString>;
|
|
2796
|
-
}, z.core.$strict>, z.ZodObject<{
|
|
2797
|
-
kind: z.ZodLiteral<"pay-per-use">;
|
|
2798
|
-
tier: z.ZodOptional<z.ZodString>;
|
|
2799
|
-
}, z.core.$strict>]>;
|
|
2800
|
-
type PlanClass = z.infer<typeof PlanClassSchema>;
|
|
4696
|
+
declare const RC_SELF_HOST_WORKER_JWT_TTL_SECONDS = 46800;
|
|
2801
4697
|
/**
|
|
2802
|
-
*
|
|
4698
|
+
* How often the SSE streams send a keepalive comment. Not a fresh number: it is the protocol's own keepalive cadence (the 15 s comments the door's client-half parser documents from live captures), and it must beat the worker transport's 45 s liveness bound (`DIY` in the CLI source), which a 15 s cadence does with two comments to spare.
|
|
2803
4699
|
*/
|
|
2804
|
-
declare
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
readonly
|
|
2813
|
-
|
|
2814
|
-
readonly
|
|
2815
|
-
readonly account?: AccountMetadata;
|
|
2816
|
-
/** The member's usage-log records from the current five-hour window on. */
|
|
2817
|
-
readonly records: readonly UsageRecord[];
|
|
2818
|
-
}
|
|
2819
|
-
/** The member last picked for this directory, kept so a conversation stays on the account whose prompt cache is warm. */
|
|
2820
|
-
interface StickyPick {
|
|
2821
|
-
readonly identity: string;
|
|
2822
|
-
readonly at: string;
|
|
2823
|
-
}
|
|
2824
|
-
interface RankPoolInput {
|
|
2825
|
-
readonly members: readonly PoolMember[];
|
|
2826
|
-
readonly nowMs: number;
|
|
2827
|
-
readonly sticky?: StickyPick;
|
|
2828
|
-
/** True when the launch continues or resumes a conversation, which belongs on the account it started on whatever the cache lifetime. */
|
|
2829
|
-
readonly resuming: boolean;
|
|
4700
|
+
declare const RC_SELF_HOST_KEEPALIVE_MS = 15000;
|
|
4701
|
+
/**
|
|
4702
|
+
* How long a session's events are retained for stream resume, and how long a streamless, trafficless session survives. One number serves both because one protocol constant derives them: the worker transport's reconnection budget is 600000 ms (`WIY` in the CLI source), so a resume can only ever name a cursor whose events are at most that old, and a worker that has been gone longer has given up by its own rules.
|
|
4703
|
+
*/
|
|
4704
|
+
declare const RC_SELF_HOST_RETENTION_MS = 600000;
|
|
4705
|
+
/** The whole credential this door's self-hosted mode mints, read back for every authenticated call and never logged: the token pair the identity's Claude Code presents, beside the organisation the minting chose. */
|
|
4706
|
+
interface RcSelfHostCredentialRecord {
|
|
4707
|
+
readonly accessToken: string;
|
|
4708
|
+
readonly refreshToken: string;
|
|
4709
|
+
readonly organizationUuid: string;
|
|
4710
|
+
readonly accountUuid: string;
|
|
2830
4711
|
}
|
|
2831
|
-
/**
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
readonly
|
|
2836
|
-
/**
|
|
2837
|
-
readonly
|
|
2838
|
-
/**
|
|
2839
|
-
readonly
|
|
2840
|
-
|
|
2841
|
-
readonly blockedUntilMs?: number;
|
|
2842
|
-
readonly plan: PlanClass;
|
|
2843
|
-
/** Human-readable facts behind the class and score, in the order they matter. */
|
|
2844
|
-
readonly reasons: readonly string[];
|
|
4712
|
+
/** Everything the service needs, injected so the decision logic runs against fakes in unit tests. */
|
|
4713
|
+
interface RcSelfHostDeps {
|
|
4714
|
+
readonly now: () => number;
|
|
4715
|
+
/** Mints the session and event ids: a v4 UUID or better in production. */
|
|
4716
|
+
readonly newUuid: () => string;
|
|
4717
|
+
/** Mints opaque token material (the worker JWTs): cryptographically random in production. */
|
|
4718
|
+
readonly randomToken: () => string;
|
|
4719
|
+
/** The minted credential this door authenticates against, read fresh so a re-mint takes effect without restarting the door; undefined while none was ever minted, in which case every authenticated call is refused. */
|
|
4720
|
+
readonly credentialRecord: () => RcSelfHostCredentialRecord | undefined;
|
|
4721
|
+
readonly log?: (line: string) => void;
|
|
2845
4722
|
}
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
readonly
|
|
2854
|
-
|
|
4723
|
+
/** The self-hosted Remote Control service: the session-family route for the pipeline, and the local answers the connect surface consults before routing or piping. */
|
|
4724
|
+
interface RcSelfHostSurface {
|
|
4725
|
+
/** The pipeline route serving the whole `/v1/code/sessions` family and the `/v1/sessions` compatibility list. */
|
|
4726
|
+
readonly route: FrontDoorRoute;
|
|
4727
|
+
/** The connect surface's local answers: which hosts it takes over as HTTP, and the requests it answers itself. */
|
|
4728
|
+
readonly local: {
|
|
4729
|
+
/** The hosts whose terminated sessions this surface needs parsed as HTTP (the control-plane host, normally byte-tapped). */
|
|
4730
|
+
readonly parsesHost: (host: string) => boolean;
|
|
4731
|
+
/** Serves one request locally; resolves false when the surface does not own the path, so routing or piping continues unchanged. */
|
|
4732
|
+
readonly serve: (host: string, request: IncomingMessage, response: ServerResponse) => Promise<boolean>;
|
|
2855
4733
|
};
|
|
4734
|
+
/** Stops the service's timers and retires every open stream. The sessions themselves are unreachable the moment the door drops them. */
|
|
4735
|
+
readonly close: () => void;
|
|
2856
4736
|
}
|
|
2857
|
-
/**
|
|
2858
|
-
|
|
2859
|
-
*
|
|
2860
|
-
* A member is `ineligible` while a window of its plan, or a refusal it last hit, still binds; it is `unknown` without recorded quota, `pay-per-use` when its usage bills by use, and otherwise `scored`. Scored members order by how much plan-size-weighted quota would expire unused per hour of runway, with any whose five-hour window would run dry at the observed pace (their own, or the person's pace on another member rescaled by plan size) placed behind those that would not. The member last picked for this directory then moves to the front if it is still usable and either the launch resumes a conversation or its prompt cache is still warm.
|
|
2861
|
-
*/
|
|
2862
|
-
declare function rankPool(input: RankPoolInput): PoolRanking;
|
|
2863
|
-
|
|
2864
|
-
/** What `pool pick` reports: the ranking a launch from `directory` would act on right now. */
|
|
2865
|
-
declare const PoolPickReportSchema: z.ZodObject<{
|
|
2866
|
-
pool: z.ZodString;
|
|
2867
|
-
directory: z.ZodString;
|
|
2868
|
-
pick: z.ZodOptional<z.ZodString>;
|
|
2869
|
-
candidates: z.ZodArray<z.ZodObject<{
|
|
2870
|
-
identity: z.ZodString;
|
|
2871
|
-
class: z.ZodEnum<{
|
|
2872
|
-
unknown: "unknown";
|
|
2873
|
-
"pay-per-use": "pay-per-use";
|
|
2874
|
-
scored: "scored";
|
|
2875
|
-
ineligible: "ineligible";
|
|
2876
|
-
}>;
|
|
2877
|
-
score: z.ZodOptional<z.ZodNumber>;
|
|
2878
|
-
feasible: z.ZodBoolean;
|
|
2879
|
-
blockedUntil: z.ZodOptional<z.ZodISODateTime>;
|
|
2880
|
-
plan: z.ZodUnion<readonly [z.ZodObject<{
|
|
2881
|
-
kind: z.ZodLiteral<"subscription">;
|
|
2882
|
-
capacity: z.ZodNumber;
|
|
2883
|
-
recognised: z.ZodBoolean;
|
|
2884
|
-
tier: z.ZodOptional<z.ZodString>;
|
|
2885
|
-
}, z.core.$strict>, z.ZodObject<{
|
|
2886
|
-
kind: z.ZodLiteral<"pay-per-use">;
|
|
2887
|
-
tier: z.ZodOptional<z.ZodString>;
|
|
2888
|
-
}, z.core.$strict>]>;
|
|
2889
|
-
reasons: z.ZodArray<z.ZodString>;
|
|
2890
|
-
}, z.core.$strict>>;
|
|
2891
|
-
missing: z.ZodArray<z.ZodString>;
|
|
2892
|
-
earliestReturn: z.ZodOptional<z.ZodObject<{
|
|
2893
|
-
identity: z.ZodString;
|
|
2894
|
-
at: z.ZodISODateTime;
|
|
2895
|
-
}, z.core.$strict>>;
|
|
2896
|
-
stickyProblem: z.ZodOptional<z.ZodString>;
|
|
2897
|
-
}, z.core.$strict>;
|
|
2898
|
-
type PoolPickReport = z.infer<typeof PoolPickReportSchema>;
|
|
2899
|
-
|
|
2900
|
-
/**
|
|
2901
|
-
* Ranks a pool exactly as a launch from `directory` would right now, without recording a pick. Shares `rankPoolFromStore` with the launcher, so what this prints is what a launch does.
|
|
2902
|
-
*/
|
|
2903
|
-
declare function collectPoolPick(params: Readonly<{
|
|
2904
|
-
paths: LayoutPaths;
|
|
2905
|
-
fs: FsPort;
|
|
2906
|
-
usageFs: FarmFs;
|
|
2907
|
-
poolName: string;
|
|
2908
|
-
pool: Pool;
|
|
2909
|
-
directory: string;
|
|
2910
|
-
nowMs: number;
|
|
2911
|
-
}>): PoolPickReport;
|
|
4737
|
+
/** Creates the self-hosted Remote Control service. One per door process; everything it holds dies with it. */
|
|
4738
|
+
declare function createRcSelfHostSurface(deps: RcSelfHostDeps): RcSelfHostSurface;
|
|
2912
4739
|
|
|
2913
|
-
/**
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
readonly
|
|
2920
|
-
/**
|
|
2921
|
-
readonly
|
|
2922
|
-
|
|
4740
|
+
/** Where the door's own copy of the minted credential lives, under the door's state directory. */
|
|
4741
|
+
declare const RC_SELF_HOST_RECORD_DIR = "rc-selfhost";
|
|
4742
|
+
/** The door's copy of the minted credential: the record `rcSelfHost.ts` reads fresh on every authenticated call. */
|
|
4743
|
+
declare const RC_SELF_HOST_RECORD_FILE = "credential.json";
|
|
4744
|
+
/** Everything the minting needs, injected so it runs against an in-memory fake filesystem in unit tests. */
|
|
4745
|
+
interface RcSelfHostMintDeps {
|
|
4746
|
+
readonly fs: Pick<FarmFs, "readFileUtf8" | "writeFilePrivate" | "mkdirPrivate">;
|
|
4747
|
+
/** The agent-shim identities directory (the mint writes inside `<identitiesDir>/<identity>/`). */
|
|
4748
|
+
readonly identitiesDir: string;
|
|
4749
|
+
/** The door's state directory (the record is written under `<frontdoorDir>/rc-selfhost/`). */
|
|
4750
|
+
readonly frontdoorDir: string;
|
|
4751
|
+
readonly identity: string;
|
|
4752
|
+
/** Mints ids: a v4 UUID or better in production. */
|
|
4753
|
+
readonly newUuid: () => string;
|
|
4754
|
+
/** Mints token material: cryptographically random bytes in production. */
|
|
4755
|
+
readonly randomToken: () => string;
|
|
4756
|
+
/** Overwrite an existing credential that is not a previous mint of this door's. */
|
|
4757
|
+
readonly force: boolean;
|
|
4758
|
+
readonly now: () => number;
|
|
2923
4759
|
}
|
|
2924
|
-
/**
|
|
2925
|
-
interface
|
|
2926
|
-
readonly
|
|
2927
|
-
|
|
2928
|
-
readonly
|
|
2929
|
-
|
|
2930
|
-
readonly
|
|
4760
|
+
/** What the minting produced: names and shapes only, never a token. */
|
|
4761
|
+
interface RcSelfHostMintResult {
|
|
4762
|
+
readonly identity: string;
|
|
4763
|
+
readonly organizationUuid: string;
|
|
4764
|
+
readonly credentialsFile: string;
|
|
4765
|
+
readonly claudeJsonFile: string;
|
|
4766
|
+
readonly recordFile: string;
|
|
4767
|
+
/** Whether a previous mint of this door's was replaced. */
|
|
4768
|
+
readonly replaced: boolean;
|
|
2931
4769
|
}
|
|
2932
|
-
/**
|
|
2933
|
-
declare function
|
|
4770
|
+
/** Reads the door's previously minted record, or undefined when none exists (or what exists does not parse). */
|
|
4771
|
+
declare function readRcSelfHostRecord(fs: Pick<FarmFs, "readFileUtf8">, frontdoorDir: string): RcSelfHostCredentialRecord | undefined;
|
|
2934
4772
|
/**
|
|
2935
|
-
*
|
|
2936
|
-
*
|
|
2937
|
-
* An absent condition is vacuously true, so `when: {}` passes; `agent-shim check` warns about that rather than erroring, since an empty object is more likely a half-finished edit than an intentional statement.
|
|
2938
|
-
*
|
|
2939
|
-
* `newerThan`, `olderThan`, and `maxSizeBytes` read the subtree-aggregated facts (`latestMtimeMs`, `totalSizeBytes`), never the entry's own inode stat: a directory's own mtime does not change when a file three levels beneath it is rewritten, and its own size is a ~4KB inode figure that says nothing about what it contains.
|
|
4773
|
+
* Mints the local credential for one identity and records the door's copy. Refuses, unless `force`, when the identity already holds an OAuth credential this door did not mint (a real claude.ai login): overwriting one silently would sign the identity out, and the mode's own contract is that no Anthropic credential is in play at all.
|
|
2940
4774
|
*/
|
|
2941
|
-
declare function
|
|
4775
|
+
declare function mintRcSelfHostCredential(deps: RcSelfHostMintDeps): RcSelfHostMintResult;
|
|
2942
4776
|
|
|
2943
|
-
/**
|
|
2944
|
-
|
|
4777
|
+
/** The outcome of authenticating the listener a front-door state file names. */
|
|
4778
|
+
type ListenerVerdict = {
|
|
4779
|
+
readonly ok: true;
|
|
4780
|
+
} | {
|
|
4781
|
+
readonly ok: false;
|
|
4782
|
+
readonly reason: string;
|
|
4783
|
+
};
|
|
4784
|
+
|
|
4785
|
+
/** Raised when the front door cannot be brought up in time or has recorded a fatal error: a routed launch has no other way to reach its provider, so it must fail rather than start a session that can never answer. */
|
|
4786
|
+
declare class FrontDoorStartError extends CliError {
|
|
2945
4787
|
constructor(message: string);
|
|
2946
4788
|
}
|
|
2947
4789
|
/** Every effect the ensure step performs, injected so it runs against fakes in tests. */
|
|
2948
|
-
interface
|
|
4790
|
+
interface EnsureFrontDoorPorts {
|
|
2949
4791
|
readonly fs: HeadroomFs;
|
|
2950
|
-
/** Zombie-aware liveness
|
|
4792
|
+
/** Zombie-aware liveness (see `realIsProcessRunning`). */
|
|
2951
4793
|
readonly isRunning: (pid: number) => boolean;
|
|
2952
4794
|
readonly now: () => number;
|
|
2953
4795
|
readonly sleep: (ms: number) => void;
|
|
2954
|
-
/** Spawns the detached supervisor
|
|
4796
|
+
/** Spawns the detached front-door supervisor, returning its pid. */
|
|
2955
4797
|
readonly spawnSupervisor: (paths: LayoutPaths) => number;
|
|
4798
|
+
/** Authenticates the provider listener on `port`: a TLS handshake chaining to agent-shim's CA and a healthy answer, with no capability sent (see `probeFrontDoorSync`). */
|
|
4799
|
+
readonly verifyListener: (port: number) => ListenerVerdict;
|
|
4800
|
+
/** Asks a running front-door supervisor to exit, without waiting for it to: the caller polls `isRunning`. Only ever called for a pid whose recorded listener has just authenticated as agent-shim's own. */
|
|
4801
|
+
readonly stopSupervisor: (pid: number) => void;
|
|
2956
4802
|
}
|
|
2957
4803
|
/**
|
|
2958
|
-
* Brings the
|
|
2959
|
-
*
|
|
2960
|
-
* The exclusive-create start lock decides which of several concurrent launches spawns the one supervisor: its holder spawns and keeps waiting like everyone else, everyone else waits on the state file, and a lock whose holder has died is removed and retried. Readiness is "state names a live supervisor, a live headroom pid, and a socket path", which the supervisor only writes after its own `/readyz` probe over that socket has passed, so polling state alone never mistakes a bound-but-not-ready socket for a usable daemon.
|
|
4804
|
+
* Brings the front door up for this launch, or finds it serving, and registers this launcher pid in its session registry: the fact that keeps the door from idling out while this session lives, and the record that holds this launch's capability token. The same lock-and-poll coordination as headroom's and the old codex daemon's ensure: the exclusive-create start lock decides which of several concurrent launches spawns the one supervisor, everyone waits on state.json, and a lock whose holder died is removed and retried. Ready means state names a live supervisor and both listeners' ports, which the supervisor writes only after both have bound (and the provider listener has answered its own health probe).
|
|
2961
4805
|
*
|
|
2962
|
-
*
|
|
4806
|
+
* A live pid in state proves nothing about who holds the port it names: the door may have crashed and left the port to anyone, or the pid may have been reused by an unrelated process. So before anything is registered or returned, the provider listener is authenticated over TLS against agent-shim's CA. A listener that fails (wrong certificate, nothing answering, a bad answer) is treated as a stale or hostile owner: its pid is distrusted for the rest of this call and a replacement supervisor is spawned, which binds a free port when the sticky one is held and is then verified in turn. If a supervisor this call spawned also fails verification, the launch is refused naming the reason and the daemon log; no capability is written and no address is handed to the child.
|
|
2963
4807
|
*/
|
|
2964
|
-
declare function
|
|
4808
|
+
declare function ensureFrontDoor(params: {
|
|
2965
4809
|
readonly paths: LayoutPaths;
|
|
2966
4810
|
readonly launcherPid: number;
|
|
2967
|
-
readonly ports:
|
|
2968
|
-
/**
|
|
2969
|
-
* The hash of the allowlist the daemon must have been started with for this launch to work, read fresh on every poll because the front door's address it contains can change while the launch waits. Given for a launch that routes a provider through headroom, whose requests come back to the front door's direct origin and are refused by a daemon that was started without it; absent for a launch that only needs Claude Code's own API, which every daemon admits.
|
|
2970
|
-
*/
|
|
2971
|
-
readonly requiredAllowlistHash?: () => string;
|
|
4811
|
+
readonly ports: EnsureFrontDoorPorts;
|
|
2972
4812
|
}): {
|
|
2973
|
-
readonly
|
|
4813
|
+
readonly port: number;
|
|
4814
|
+
readonly connectPort: number;
|
|
4815
|
+
readonly token: string;
|
|
2974
4816
|
};
|
|
2975
4817
|
|
|
2976
|
-
/**
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
/**
|
|
2980
|
-
|
|
2981
|
-
/** The install spec as configured (`headroom.source`), already defaulted. */
|
|
2982
|
-
readonly source: string;
|
|
2983
|
-
/** `headroom.idleShutdownMinutes`, already defaulted. */
|
|
2984
|
-
readonly idleShutdownMinutes: number;
|
|
2985
|
-
/** The token-saving settings (`mode`, `targetRatio`, `ccr`, the rollout channel and its opt-ins), as configured; unset fields leave headroom on its own defaults. */
|
|
2986
|
-
readonly settings: HeadroomSettings;
|
|
4818
|
+
/** A bound front-door listener in this process, and how to stop it. */
|
|
4819
|
+
interface FrontDoorListenerHandle {
|
|
4820
|
+
readonly port: number;
|
|
4821
|
+
/** Stops accepting, ends every live connection, and resolves once the port is released. */
|
|
4822
|
+
readonly close: () => Promise<void>;
|
|
2987
4823
|
}
|
|
2988
|
-
/**
|
|
2989
|
-
|
|
2990
|
-
/**
|
|
2991
|
-
* Every effect the supervisor performs, injected so the whole lifecycle is testable against fakes: no real process, port, clock, or HTTP call ever happens in a unit test.
|
|
2992
|
-
*/
|
|
2993
|
-
interface SupervisorPorts {
|
|
4824
|
+
/** Every effect the front-door supervisor performs, injected so its whole lifecycle runs against fakes: no real process, port, clock or listener in a unit test. */
|
|
4825
|
+
interface FrontDoorSupervisorPorts {
|
|
2994
4826
|
readonly fs: HeadroomFs;
|
|
2995
4827
|
readonly paths: LayoutPaths;
|
|
2996
4828
|
readonly ownPid: number;
|
|
2997
4829
|
readonly now: () => number;
|
|
2998
|
-
/**
|
|
2999
|
-
* Waits `ms`, yielding to the event loop while it does. Deliberately NOT a synchronous Atomics.wait-style sleep: the real supervisor learns of its child's death through the ChildProcess exit event, and a blocking sleep would stop the event loop from ever delivering it (the exact failure that left an unreaped zombie answering liveness checks as alive).
|
|
3000
|
-
*/
|
|
4830
|
+
/** An event-loop-yielding wait, for the same reason headroom's is: nothing else would ever run between ticks. */
|
|
3001
4831
|
readonly sleep: (ms: number) => Promise<void>;
|
|
3002
|
-
/**
|
|
3003
|
-
* Zombie-aware liveness, and for a daemon this supervisor spawned, exit-event-backed: the implementation keeps the spawned ChildProcess handle, consumes its exit event (which is also what reaps it), and reports the pid as not running from that moment. A bare signal-0 check is not enough, because a defunct process still answers it.
|
|
3004
|
-
*/
|
|
4832
|
+
/** Zombie-aware liveness, the notion every coordination decision in this project uses. */
|
|
3005
4833
|
readonly isRunning: (pid: number) => boolean;
|
|
3006
|
-
/** The platform facts and owner-only checks the daemon's socket directory is prepared and verified with (see `prepareHeadroomSocket`). */
|
|
3007
|
-
readonly socketTrust: HeadroomSocketTrustPorts;
|
|
3008
|
-
/**
|
|
3009
|
-
* Starts `headroom proxy` serving on the unix socket `socketPath` (and on no TCP port) with the given allowlist, returning its pid. Output goes to the daemon log. The implementation must keep the ChildProcess handle and attach an exit listener (detaching the process is fine; unref'ing a child you still need events from is not, since without the listener nothing reaps it and it lingers as a zombie).
|
|
3010
|
-
*/
|
|
3011
|
-
readonly spawnHeadroom: (socketPath: string, allowlist: readonly string[], settings: Readonly<HeadroomSettings>) => number;
|
|
3012
|
-
/** Reads the headroom config block as it stands on disk now. The supervisor calls it every tick, so a changed `source` or setting is noticed while the daemon runs and applied by the same quiet-registry restart an allowlist change gets. */
|
|
3013
|
-
readonly readConfig: () => HeadroomSupervisorConfig;
|
|
3014
|
-
/** Stops a process the supervisor owns, escalating SIGTERM to SIGKILL on a bounded timeout (see `stopSupervisedProcess`). */
|
|
3015
|
-
readonly stopProcess: (pid: number) => void;
|
|
3016
|
-
/** True once `GET /readyz` over the unix socket succeeds. */
|
|
3017
|
-
readonly ready: (socketPath: string) => Promise<boolean>;
|
|
3018
|
-
/** Runs `uv tool install <spec>`, logging output to the daemon log. Returns ok=false with the error when `uv` is absent or the install fails. */
|
|
3019
|
-
readonly install: (spec: string) => {
|
|
3020
|
-
readonly ok: boolean;
|
|
3021
|
-
readonly error?: string;
|
|
3022
|
-
};
|
|
3023
|
-
/** The installed `headroom --version` output, or undefined when the binary is not on PATH. */
|
|
3024
|
-
readonly headroomVersion: () => string | undefined;
|
|
3025
|
-
/** The commit the installed headroom was built from, as the install itself records it (`direct_url.json`), or undefined when it was not installed from a git source. */
|
|
3026
|
-
readonly installedCommit: () => string | undefined;
|
|
3027
|
-
readonly log: (line: string) => void;
|
|
3028
|
-
}
|
|
3029
|
-
/** Options for `runSupervisor`. */
|
|
3030
|
-
interface RunSupervisorOptions {
|
|
3031
4834
|
/**
|
|
3032
|
-
*
|
|
4835
|
+
* Starts the provider listener in this process on `preferredPort` (falling back to any free port when the sticky one is taken, decided at bind time rather than by a racy check-then-bind probe) and resolves once it has bound and answered its own health probe over TLS. This is the HTTPS listener every provider session's base URL points at, serving a loopback leaf signed by agent-shim's CA.
|
|
3033
4836
|
*/
|
|
3034
|
-
readonly
|
|
3035
|
-
}
|
|
3036
|
-
/**
|
|
3037
|
-
* Runs the headroom supervisor loop: install the daemon, start it, keep it alive (for crash or drift), and stop it after the configured idle period with an empty session registry. Returns the process exit code (0 for an idle shutdown, 1 for a fatal setup failure).
|
|
3038
|
-
*
|
|
3039
|
-
* Every effect flows through `ports`, so the whole loop is unit-testable with a fake clock, filesystem, and processes. The loop awaits its sleeps, which in the real implementation run on a timer: between ticks the event loop turns, the spawned child's exit event is delivered (and the child thereby reaped), and the next tick's liveness check reads the truth.
|
|
3040
|
-
*/
|
|
3041
|
-
declare function runSupervisor(initialConfig: HeadroomSupervisorConfig, ports: SupervisorPorts, options?: RunSupervisorOptions): Promise<number>;
|
|
3042
|
-
|
|
3043
|
-
/**
|
|
3044
|
-
* The environment variables that authenticate Claude Code directly from the process environment, ahead of any stored identity credential. If any of these is set, every identity would silently authenticate as the same key/token/backend while it's set — defeating the entire premise of separate identities. Order here is also lookup order: `detectAmbientCredential` reports the first one found.
|
|
3045
|
-
*/
|
|
3046
|
-
declare const AMBIENT_CREDENTIAL_VARS: readonly ["ANTHROPIC_API_KEY", "ANTHROPIC_AUTH_TOKEN", "CLAUDE_CODE_OAUTH_TOKEN", "CLAUDE_CODE_USE_BEDROCK", "CLAUDE_CODE_USE_VERTEX", "CLAUDE_CODE_USE_FOUNDRY"];
|
|
3047
|
-
type AmbientCredentialVar = (typeof AMBIENT_CREDENTIAL_VARS)[number];
|
|
3048
|
-
/** Which guarded variable was found set, and to what. */
|
|
3049
|
-
interface AmbientCredentialDetection {
|
|
3050
|
-
readonly variable: AmbientCredentialVar;
|
|
3051
|
-
}
|
|
3052
|
-
/** A credential this launch itself exports to the child: the variable it lands in and its value. */
|
|
3053
|
-
interface InjectedCredential {
|
|
3054
|
-
readonly variable: CredentialTargetVar;
|
|
3055
|
-
readonly token: string;
|
|
3056
|
-
}
|
|
3057
|
-
/**
|
|
3058
|
-
* Detects whether any of `AMBIENT_CREDENTIAL_VARS` is set to a non-empty value in `env`, returning the first one found in declared order, or undefined when none are set.
|
|
3059
|
-
*
|
|
3060
|
-
* An empty string counts as unset, not set — confirmed load-bearing: one of Joe's real wrapper scripts (`o`, running Claude Code against OpenRouter) does `export ANTHROPIC_API_KEY=""` specifically to *clear* it so `ANTHROPIC_AUTH_TOKEN` takes effect instead, and this must never trip the guard.
|
|
3061
|
-
*
|
|
3062
|
-
* `injected`, when given, is the credential this launch exports for its own identity. Its variable holding exactly that value is not ambient: it is what a agent-shim launch of the same identity left in the environment of the session this one starts from (a `claude @work` run inside a `claude @work` session). The same variable holding any other value still counts.
|
|
3063
|
-
*/
|
|
3064
|
-
declare function detectAmbientCredential(env: Readonly<Record<string, string | undefined>>, injected?: InjectedCredential): AmbientCredentialDetection | undefined;
|
|
3065
|
-
/**
|
|
3066
|
-
* Builds the exact refusal message: which variable was found, why it matters, and the two ways to opt in (a one-off env var, or a persistent per-identity setting). Mirrors the message documented in the project's README. `identityName` is included in the persistent-opt-in command when known; when no identity has been resolved yet (e.g. the `CLAUDE_CONFIG_DIR`-already-set escape hatch, or no identity resolved at all), a generic `<name>` placeholder is used instead, matching the README's own generic wording.
|
|
3067
|
-
*/
|
|
3068
|
-
declare function formatAmbientCredentialGuardMessage(variable: AmbientCredentialVar, identityName?: string): string;
|
|
3069
|
-
/** Inputs to the ambient-credential guard evaluation. */
|
|
3070
|
-
interface EvaluateAmbientCredentialGuardParams {
|
|
3071
|
-
readonly env: Readonly<Record<string, string | undefined>>;
|
|
3072
|
-
/** The active identity's own `allowAmbientCredential` setting from its `identity.json`, or false when no identity is known. */
|
|
3073
|
-
readonly allowAmbientCredential: boolean;
|
|
3074
|
-
/** True when `AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL=1` is set for this one invocation. */
|
|
3075
|
-
readonly allowAmbientCredentialOverride: boolean;
|
|
3076
|
-
/** The active identity's name, for the message's persistent-opt-in command. Undefined when no identity is known. */
|
|
3077
|
-
readonly identityName?: string;
|
|
4837
|
+
readonly startProviderListener: (preferredPort: number | undefined) => Promise<FrontDoorListenerHandle>;
|
|
3078
4838
|
/**
|
|
3079
|
-
*
|
|
3080
|
-
*/
|
|
3081
|
-
readonly
|
|
3082
|
-
/**
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
readonly
|
|
3090
|
-
readonly
|
|
3091
|
-
readonly message: string;
|
|
3092
|
-
};
|
|
3093
|
-
/**
|
|
3094
|
-
* Evaluates the ambient-credential guard: refuses unless no guarded variable is set, or the active identity opted in (`allowAmbientCredential: true`), or this one invocation opted in (`AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL=1`), or a provider takes over the child's credential (see `providerSelected`).
|
|
3095
|
-
*
|
|
3096
|
-
* This guard is about credential isolation, not identity/config-dir selection — it must still run even when the `CLAUDE_CONFIG_DIR`-already-set escape hatch applies (callers pass `allowAmbientCredential: false` and no `identityName` in that case, since there is no active identity to consult).
|
|
3097
|
-
*/
|
|
3098
|
-
declare function evaluateAmbientCredentialGuard(params: EvaluateAmbientCredentialGuardParams): AmbientCredentialGuardResult;
|
|
3099
|
-
|
|
3100
|
-
/** Raised by any operation that requires an identity to already exist, when it does not. */
|
|
3101
|
-
declare class IdentityNotFoundError extends CliError {
|
|
3102
|
-
readonly name: string;
|
|
3103
|
-
constructor(name: string);
|
|
3104
|
-
}
|
|
3105
|
-
/** Raised by `addIdentity` when an identity with the given name already has an `identity.json`. */
|
|
3106
|
-
declare class IdentityAlreadyExistsError extends CliError {
|
|
3107
|
-
readonly identityName: string;
|
|
3108
|
-
constructor(identityName: string);
|
|
3109
|
-
}
|
|
3110
|
-
/** Raised by `addIdentity` when `name` fails `IdentitySchema`'s own naming rule — it must start with a letter or number and may then contain letters, numbers, dots, hyphens, underscores, and at signs, so an email address names an identity directly while a *leading* `@` stays invalid (it would collide with the `@name` selector syntax's first-`@` split). */
|
|
3111
|
-
declare class InvalidIdentityNameError extends CliError {
|
|
3112
|
-
readonly attemptedName: string;
|
|
3113
|
-
constructor(attemptedName: string);
|
|
3114
|
-
}
|
|
3115
|
-
declare function identityExists(paths: LayoutPaths, name: string): boolean;
|
|
3116
|
-
/** Reads and validates one identity's `identity.json`, or undefined when it does not exist. */
|
|
3117
|
-
declare function readIdentity(paths: LayoutPaths, name: string): Identity | undefined;
|
|
3118
|
-
/**
|
|
3119
|
-
* Creates a new identity: validates `name` against `IdentitySchema`'s own naming rule and writes a fresh `identity.json` with `allowAmbientCredential: false` and no `defaultConfigProfile`.
|
|
3120
|
-
*
|
|
3121
|
-
* Throws `IdentityAlreadyExistsError` if an identity with this name already has an `identity.json` — `add` never silently overwrites an existing identity. Throws `InvalidIdentityNameError` when `name` fails `IdentitySchema`'s naming rule, rather than letting the underlying `ZodError` escape as an unhandled crash.
|
|
3122
|
-
*/
|
|
3123
|
-
declare function addIdentity(paths: LayoutPaths, name: string): Identity;
|
|
3124
|
-
/**
|
|
3125
|
-
* Persists `name` as the active identity, written atomically as plain text (not JSON — this file is read by `decideIdentity` in `src/launcher/identity.ts` via a simple UTF-8 read-and-trim, matching the README's documented `~/.agent-shim/active-identity` file).
|
|
3126
|
-
*
|
|
3127
|
-
* `name` may be a `pool:<name>` selector, which makes launches pick a member of that pool. Throws `IdentityNotFoundError` when no identity with this name exists yet, and `PoolNotFoundError` for a pool that is not defined: selecting either would silently persist a name nothing else can ever load.
|
|
3128
|
-
*/
|
|
3129
|
-
declare function useIdentity(paths: LayoutPaths, name: string): void;
|
|
3130
|
-
/** Reads the persisted active-identity file, or undefined when none is set. */
|
|
3131
|
-
declare function readActiveIdentity(paths: LayoutPaths): string | undefined;
|
|
3132
|
-
/**
|
|
3133
|
-
* Whether a directory name directly under `identitiesDir` names an actual identity, rather than one of agent-shim's own farm directories.
|
|
3134
|
-
*
|
|
3135
|
-
* `IdentitySchema` requires an identity name to start with a letter or digit, so a leading `.` can only be a resync's own bookkeeping: a `.<identity>.scratch.<suffix>` tree still being built, or a `.<identity>.previous.<suffix>` superseded farm retained for `agent-shim identity resolve-conflicts`. Neither is an identity, and neither should be reported as a broken one for lacking an `identity.json` a resync never put there.
|
|
3136
|
-
*/
|
|
3137
|
-
declare function isIdentityDirectoryName(name: string): boolean;
|
|
3138
|
-
/** One identity as reported by `listIdentities`, whose `identity.json` parsed and validated cleanly. */
|
|
3139
|
-
interface IdentityListEntry {
|
|
3140
|
-
readonly name: string;
|
|
3141
|
-
readonly identity: Identity;
|
|
3142
|
-
readonly isActive: boolean;
|
|
3143
|
-
readonly problem?: never;
|
|
4839
|
+
* Starts the CONNECT surface in this process on `preferredPort` (same bind-time fallback): the TLS-terminating listener an OAuth session's HTTPS_PROXY points at. Bound before any state names it, so an OAuth launch never finds one listener up without the other.
|
|
4840
|
+
*/
|
|
4841
|
+
readonly startConnectListener: (preferredPort: number | undefined) => Promise<FrontDoorListenerHandle>;
|
|
4842
|
+
/**
|
|
4843
|
+
* Starts the direct listener on `preferredPort` (same bind-time fallback): the same routes as the provider listener, minus the headroom hop, over plain HTTP because headroom is what connects to it. Headroom forwards routed traffic back here, which is what keeps the hop from looping, and the port is sticky like the others because headroom's allowlist admits its exact origin. It admits only the hop's own requests and holds no credential until it redeems one from the hop's custody.
|
|
4844
|
+
*/
|
|
4845
|
+
readonly startDirectListener: (preferredPort: number | undefined) => Promise<FrontDoorListenerHandle>;
|
|
4846
|
+
/**
|
|
4847
|
+
* Stops the Remote Control stream hub: persists every live attachment's sequence cursor synchronously, then frees the dials. Called exactly once on every exit the supervisor owns, after every listener it started is down (a live listener could still settle an observed Remote Control exchange, and the reconcile that follows would re-attach a stream the close had just ended) and before the final state write and the process's exit.
|
|
4848
|
+
*/
|
|
4849
|
+
readonly closeRcStreamHub: () => void;
|
|
4850
|
+
readonly log: (line: string) => void;
|
|
3144
4851
|
}
|
|
3145
|
-
/**
|
|
3146
|
-
interface
|
|
3147
|
-
|
|
3148
|
-
readonly
|
|
3149
|
-
readonly isActive: boolean;
|
|
3150
|
-
readonly problem: string;
|
|
4852
|
+
/** Options for `runFrontDoorSupervisor`. */
|
|
4853
|
+
interface RunFrontDoorSupervisorOptions {
|
|
4854
|
+
/** Bounds the loop's iterations so a test can observe steady state; such a run returns `FRONTDOOR_SUPERVISOR_STILL_RUNNING`. */
|
|
4855
|
+
readonly tickLimit?: number;
|
|
3151
4856
|
}
|
|
3152
|
-
/** Either shape `listIdentities` can report, discriminated by which of `identity`/`problem` is present rather than by a tag field — the two are never simultaneously satisfiable. */
|
|
3153
|
-
type IdentityListing = IdentityListEntry | UnreadableIdentityListEntry;
|
|
3154
4857
|
/**
|
|
3155
|
-
*
|
|
4858
|
+
* Runs the front-door supervisor: binds all three listeners (the HTTPS provider listener, the CONNECT surface and the plain-HTTP direct listener, each on its sticky port), records the serving state, and shuts down after `idleShutdownMinutes` with an empty session registry. Returns the exit code: 0 for an idle shutdown, 1 for a fatal start failure.
|
|
3156
4859
|
*
|
|
3157
|
-
*
|
|
3158
|
-
*/
|
|
3159
|
-
declare function listIdentities(paths: LayoutPaths): readonly IdentityListing[];
|
|
3160
|
-
/**
|
|
3161
|
-
* Sets `identity`'s `defaultConfigProfile` field, or clears it when `profileName` is undefined. Throws `IdentityNotFoundError` when the identity does not exist. Whether the profile exists is the caller's concern: `identity set --default-profile` checks it first.
|
|
4860
|
+
* The listeners live in this process, so there is no child to keep alive: a crash of this process is a crash of every routed session's door at once, and recovery is the next launch's ensure spawning a replacement on the same sticky ports, which is exactly the failure model the issue asks to settle with tests. Keeping the headroom daemon alive is the headroom supervisor's job, not this one's; the two daemons idle out independently.
|
|
3162
4861
|
*/
|
|
3163
|
-
declare function
|
|
4862
|
+
declare function runFrontDoorSupervisor(idleShutdownMinutes: number, ports: FrontDoorSupervisorPorts, options?: RunFrontDoorSupervisorOptions): Promise<number>;
|
|
4863
|
+
|
|
3164
4864
|
/**
|
|
3165
|
-
*
|
|
4865
|
+
* The read side of the usage store: pure over an injected filesystem, so the CLI, the library surface and tests all read the same way, and nothing here writes.
|
|
3166
4866
|
*/
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
readonly
|
|
3172
|
-
|
|
3173
|
-
}
|
|
4867
|
+
/** The filesystem reads the usage store's readers need. */
|
|
4868
|
+
type UsageReadFs = Pick<FarmFs, "readFileUtf8" | "readdir">;
|
|
4869
|
+
/** Raised for a snapshot file that exists but does not hold a snapshot of this schema version. */
|
|
4870
|
+
declare class UsageSnapshotError extends Error {
|
|
4871
|
+
readonly file: string;
|
|
4872
|
+
constructor(file: string, detail: string);
|
|
4873
|
+
}
|
|
4874
|
+
/** The path of an identity's snapshot. Throws for an invalid identity name, which could otherwise name a path outside the snapshots directory. */
|
|
4875
|
+
declare function snapshotPath(snapshotsDir: string, identity: string): string;
|
|
4876
|
+
/** Reads one identity's snapshot: undefined when it has none yet, `UsageSnapshotError` when the file is there but unreadable. */
|
|
4877
|
+
declare function readUsageSnapshot(fs: Pick<FarmFs, "readFileUtf8">, snapshotsDir: string, identity: string): UsageSnapshot | undefined;
|
|
4878
|
+
/** Reads every identity's snapshot, by identity name. */
|
|
4879
|
+
declare function listUsageSnapshots(fs: UsageReadFs, snapshotsDir: string): readonly UsageSnapshot[];
|
|
4880
|
+
|
|
4881
|
+
/** A quota window as it stands at a given instant. */
|
|
4882
|
+
interface EffectiveWindow {
|
|
4883
|
+
/** True when the window's reset time has passed, so the recorded observation describes a window that no longer exists. */
|
|
4884
|
+
readonly reset: boolean;
|
|
4885
|
+
/** The fraction used: 0 for a reset window, otherwise what was last observed (a lower bound, since utilisation only rises within a window), or undefined when none was reported. */
|
|
4886
|
+
readonly utilization?: number;
|
|
4887
|
+
/** The reset instant, for a window that has not reset yet and reported one. */
|
|
4888
|
+
readonly resetsAtMs?: number;
|
|
4889
|
+
/** The window's own status, for a window that has not reset yet. */
|
|
4890
|
+
readonly status?: string;
|
|
4891
|
+
}
|
|
4892
|
+
/** Reads a recorded window at `nowMs`: a window whose reset has passed is empty and carries no status, so every consumer agrees on what an old observation still means. */
|
|
4893
|
+
declare function effectiveWindow(window: Readonly<QuotaWindow>, nowMs: number): EffectiveWindow;
|
|
4894
|
+
|
|
3174
4895
|
/**
|
|
3175
|
-
*
|
|
4896
|
+
* What an account's plan means for picking it: a subscription with a capacity relative to the smallest paid tier, or an account billed by use.
|
|
3176
4897
|
*/
|
|
3177
|
-
declare
|
|
4898
|
+
declare const PlanClassSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
4899
|
+
kind: z.ZodLiteral<"subscription">;
|
|
4900
|
+
capacity: z.ZodNumber;
|
|
4901
|
+
recognised: z.ZodBoolean;
|
|
4902
|
+
tier: z.ZodOptional<z.ZodString>;
|
|
4903
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
4904
|
+
kind: z.ZodLiteral<"pay-per-use">;
|
|
4905
|
+
tier: z.ZodOptional<z.ZodString>;
|
|
4906
|
+
}, z.core.$strict>]>;
|
|
4907
|
+
type PlanClass = z.infer<typeof PlanClassSchema>;
|
|
3178
4908
|
/**
|
|
3179
|
-
*
|
|
4909
|
+
* Classifies an account from the rate-limit tier of its stored login (`organizationRateLimitTier`, which decides the organisation's limits, then `userRateLimitTier`). The tier strings are free text on Anthropic's side, so only the shapes seen are read: a trailing `<n>x` is that multiple, a bare `pro` is 1, a `zero` tier is pay-per-use. Anything else is a subscription of unrecognised size, counted as 1 and marked so the ranking can say it guessed.
|
|
3180
4910
|
*/
|
|
3181
|
-
declare function
|
|
4911
|
+
declare function planOf(account: AccountMetadata | undefined): PlanClass;
|
|
3182
4912
|
|
|
3183
|
-
/**
|
|
3184
|
-
declare
|
|
3185
|
-
|
|
3186
|
-
|
|
4913
|
+
/** Anthropic's longest prompt-cache lifetime (the one-hour tier): a conversation resumed within it still has a warm cache on the account that served it, and the cache is per organisation, so it is lost by switching. */
|
|
4914
|
+
declare const PROMPT_CACHE_TTL_MS: number;
|
|
4915
|
+
/** The state a member's ranking was built from. */
|
|
4916
|
+
interface PoolMember {
|
|
4917
|
+
readonly identity: string;
|
|
4918
|
+
/** The identity's usage snapshot, when it has one. */
|
|
4919
|
+
readonly snapshot?: UsageSnapshot;
|
|
4920
|
+
/** Why the member's recorded state could not be read (a corrupt or newer-schema snapshot, an unreadable login file), when that is the case. */
|
|
4921
|
+
readonly readError?: string;
|
|
4922
|
+
readonly account?: AccountMetadata;
|
|
4923
|
+
/** The member's usage-log records from the current five-hour window on. */
|
|
4924
|
+
readonly records: readonly UsageRecord[];
|
|
3187
4925
|
}
|
|
3188
|
-
/**
|
|
3189
|
-
|
|
3190
|
-
readonly
|
|
3191
|
-
|
|
4926
|
+
/** The member last picked for this directory, kept so a conversation stays on the account whose prompt cache is warm. */
|
|
4927
|
+
interface StickyPick {
|
|
4928
|
+
readonly identity: string;
|
|
4929
|
+
readonly at: string;
|
|
3192
4930
|
}
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
readonly
|
|
3196
|
-
|
|
4931
|
+
interface RankPoolInput {
|
|
4932
|
+
readonly members: readonly PoolMember[];
|
|
4933
|
+
readonly nowMs: number;
|
|
4934
|
+
readonly sticky?: StickyPick;
|
|
4935
|
+
/** True when the launch continues or resumes a conversation, which belongs on the account it started on whatever the cache lifetime. */
|
|
4936
|
+
readonly resuming: boolean;
|
|
3197
4937
|
}
|
|
3198
|
-
/**
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
readonly
|
|
3209
|
-
readonly
|
|
4938
|
+
/** In pick order. `scored` has usable quota data; `unknown` has none (never recorded, or unreadable); `pay-per-use` bills by use instead of drawing on a plan; `ineligible` is refused right now. */
|
|
4939
|
+
type CandidateClass = "scored" | "unknown" | "pay-per-use" | "ineligible";
|
|
4940
|
+
interface Candidate {
|
|
4941
|
+
readonly identity: string;
|
|
4942
|
+
readonly class: CandidateClass;
|
|
4943
|
+
/** Plan-size-weighted remaining quota per hour until its reset: higher is more wasted if left unused. Present for `scored` only. */
|
|
4944
|
+
readonly score?: number;
|
|
4945
|
+
/** False when the five-hour window would run dry, at the observed pace, before it resets. A `scored` candidate that is not feasible ranks below every feasible one. */
|
|
4946
|
+
readonly feasible: boolean;
|
|
4947
|
+
/** When an `ineligible` candidate can be used again. */
|
|
4948
|
+
readonly blockedUntilMs?: number;
|
|
4949
|
+
readonly plan: PlanClass;
|
|
4950
|
+
/** Human-readable facts behind the class and score, in the order they matter. */
|
|
4951
|
+
readonly reasons: readonly string[];
|
|
4952
|
+
}
|
|
4953
|
+
interface PoolRanking {
|
|
4954
|
+
/** Every member, best first. */
|
|
4955
|
+
readonly candidates: readonly Candidate[];
|
|
4956
|
+
/** The member to launch on: the best one that is not refused. Undefined when every member is refused. */
|
|
4957
|
+
readonly pick?: Candidate;
|
|
4958
|
+
/** When nothing can be picked, the soonest any member comes back. */
|
|
4959
|
+
readonly earliestReturn?: {
|
|
4960
|
+
readonly identity: string;
|
|
4961
|
+
readonly atMs: number;
|
|
4962
|
+
};
|
|
3210
4963
|
}
|
|
3211
|
-
/** Lists every configuration profile under `configProfilesDir` that has a valid `<name>.json`. */
|
|
3212
|
-
declare function listProfiles(paths: LayoutPaths): readonly ProfileListEntry[];
|
|
3213
|
-
/** Reads the user-global `~/.agent-shim/config.json`, or undefined when it does not exist. */
|
|
3214
|
-
declare function readGlobalConfig(paths: LayoutPaths): GlobalConfig | undefined;
|
|
3215
|
-
/** Sets the user-global default configuration profile in `~/.agent-shim/config.json`, creating the file if it doesn't exist yet. Whether the profile exists is the caller's concern: `profile use` checks it first. */
|
|
3216
|
-
declare function setGlobalDefaultProfile(paths: LayoutPaths, name: string): GlobalConfig;
|
|
3217
|
-
/**
|
|
3218
|
-
* Merges `patch` (from one or more `--category cat=bool` flags) into `profile`'s own `categories` object and writes it back.
|
|
3219
|
-
*
|
|
3220
|
-
* Throws `InvalidCategoryNameError` for any key that isn't one of the four overridable categories — `secret` can never be toggled by any configuration layer, this included.
|
|
3221
|
-
*/
|
|
3222
|
-
declare function setProfileCategories(paths: LayoutPaths, name: string, patch: Readonly<Record<string, boolean>>): ConfigProfile;
|
|
3223
4964
|
/**
|
|
3224
|
-
*
|
|
4965
|
+
* Ranks `members` for a launch.
|
|
3225
4966
|
*
|
|
3226
|
-
*
|
|
4967
|
+
* A member is `ineligible` while a window of its plan, or a refusal it last hit, still binds; it is `unknown` without recorded quota, `pay-per-use` when its usage bills by use, and otherwise `scored`. Scored members order by how much plan-size-weighted quota would expire unused per hour of runway, with any whose five-hour window would run dry at the observed pace (their own, or the person's pace on another member rescaled by plan size) placed behind those that would not. The member last picked for this directory then moves to the front if it is still usable and either the launch resumes a conversation or its prompt cache is still warm.
|
|
3227
4968
|
*/
|
|
3228
|
-
declare function
|
|
4969
|
+
declare function rankPool(input: RankPoolInput): PoolRanking;
|
|
4970
|
+
|
|
3229
4971
|
/**
|
|
3230
|
-
*
|
|
4972
|
+
* Ranks a pool exactly as a launch from `directory` would right now, without recording a pick. Shares `rankPoolFromStore` with the launcher, so what this prints is what a launch does.
|
|
3231
4973
|
*/
|
|
3232
|
-
declare function
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
4974
|
+
declare function collectPoolPick(params: Readonly<{
|
|
4975
|
+
paths: LayoutPaths;
|
|
4976
|
+
fs: FsPort;
|
|
4977
|
+
usageFs: FarmFs;
|
|
4978
|
+
poolName: string;
|
|
4979
|
+
pool: Pool;
|
|
4980
|
+
directory: string;
|
|
4981
|
+
nowMs: number;
|
|
4982
|
+
}>): PoolPickReport;
|
|
3240
4983
|
|
|
3241
|
-
/**
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
account: z.ZodOptional<z.ZodString>;
|
|
3263
|
-
}, z.core.$strict>;
|
|
3264
|
-
}, z.core.$strict>, z.ZodObject<{
|
|
3265
|
-
literal: z.ZodString;
|
|
3266
|
-
}, z.core.$strict>]>;
|
|
3267
|
-
}, z.core.$strict>;
|
|
3268
|
-
type CachedCredential = z.infer<typeof CachedCredentialSchema>;
|
|
4984
|
+
/** Everything a `when` condition can be evaluated against, injected rather than read. */
|
|
4985
|
+
interface ConditionContext {
|
|
4986
|
+
readonly nowMs: number;
|
|
4987
|
+
/** Facts about the specific entry being decided. Absent when evaluating a rule-level condition that has no single entry (a directory rule's own `when`). */
|
|
4988
|
+
readonly fact?: EntryFact;
|
|
4989
|
+
/** The branch checked out at `cwd`, or undefined when `cwd` is not in a repository. */
|
|
4990
|
+
readonly branch?: string;
|
|
4991
|
+
/** True when the repository is in detached-HEAD state, in which case no `branch` condition can match. */
|
|
4992
|
+
readonly branchDetached?: boolean;
|
|
4993
|
+
readonly env: Readonly<Record<string, string | undefined>>;
|
|
4994
|
+
}
|
|
4995
|
+
/** The result of evaluating one `when` object. */
|
|
4996
|
+
interface WhenEvaluation {
|
|
4997
|
+
readonly passed: boolean;
|
|
4998
|
+
/** Which condition fields were present and evaluated. */
|
|
4999
|
+
readonly checked: readonly string[];
|
|
5000
|
+
/** Which of those fields did not hold. Empty when `passed` is true. */
|
|
5001
|
+
readonly failed: readonly string[];
|
|
5002
|
+
}
|
|
5003
|
+
/** True when `branch` matches `pattern`. The pattern is glob-capable (`client/*`); a detached HEAD or a non-repository directory never matches. */
|
|
5004
|
+
declare function matchBranch(pattern: string, branch: string | undefined, detached?: boolean): boolean;
|
|
3269
5005
|
/**
|
|
3270
|
-
*
|
|
5006
|
+
* Evaluates a `when` object. Every present field must hold — conditions AND together within one object.
|
|
5007
|
+
*
|
|
5008
|
+
* An absent condition is vacuously true, so `when: {}` passes; `agent-shim check` warns about that rather than erroring, since an empty object is more likely a half-finished edit than an intentional statement.
|
|
5009
|
+
*
|
|
5010
|
+
* `newerThan`, `olderThan`, and `maxSizeBytes` read the subtree-aggregated facts (`latestMtimeMs`, `totalSizeBytes`), never the entry's own inode stat: a directory's own mtime does not change when a file three levels beneath it is rewritten, and its own size is a ~4KB inode figure that says nothing about what it contains.
|
|
3271
5011
|
*/
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
5012
|
+
declare function evaluateWhen(when: WhenCondition | undefined, context: ConditionContext): WhenEvaluation;
|
|
5013
|
+
|
|
5014
|
+
/** Raised when the daemon cannot be brought up in time, or reports a fatal `lastError`: a launch that asked for headroom must never silently fall back to a direct connection. */
|
|
5015
|
+
declare class HeadroomStartError extends CliError {
|
|
5016
|
+
constructor(message: string);
|
|
5017
|
+
}
|
|
5018
|
+
/** Every effect the ensure step performs, injected so it runs against fakes in tests. */
|
|
5019
|
+
interface EnsureHeadroomPorts {
|
|
5020
|
+
readonly fs: HeadroomFs;
|
|
5021
|
+
/** Zombie-aware liveness: a supervisor or daemon that exited without being reaped still answers signal 0 as alive, but will never serve a request or write state, so it must read as dead here (see `realIsProcessRunning`). */
|
|
5022
|
+
readonly isRunning: (pid: number) => boolean;
|
|
5023
|
+
readonly now: () => number;
|
|
5024
|
+
readonly sleep: (ms: number) => void;
|
|
5025
|
+
/** Spawns the detached supervisor process that owns the headroom daemon, returning its pid. */
|
|
5026
|
+
readonly spawnSupervisor: (paths: LayoutPaths) => number;
|
|
3276
5027
|
}
|
|
3277
5028
|
/**
|
|
3278
|
-
*
|
|
5029
|
+
* Brings the headroom daemon up for this launch, or finds it already running, and registers this launcher pid in its session registry (the fact that keeps the daemon alive and defers drift restarts until this launch is done).
|
|
5030
|
+
*
|
|
5031
|
+
* The exclusive-create start lock decides which of several concurrent launches spawns the one supervisor: its holder spawns and keeps waiting like everyone else, everyone else waits on the state file, and a lock whose holder has died is removed and retried. Readiness is "state names a live supervisor, a live headroom pid, and a socket path", which the supervisor only writes after its own `/readyz` probe over that socket has passed, so polling state alone never mistakes a bound-but-not-ready socket for a usable daemon.
|
|
5032
|
+
*
|
|
5033
|
+
* Throws `HeadroomStartError` (naming the daemon log path and any recorded `lastError`) when the daemon is not up within `HEADROOM_START_TIMEOUT_MS`, or when a live supervisor has recorded a fatal error (a platform without unix sockets and a socket directory that fails the owner-only check are recorded this way, so the launch fails with the reason).
|
|
3279
5034
|
*/
|
|
3280
|
-
|
|
3281
|
-
readonly
|
|
3282
|
-
readonly
|
|
3283
|
-
|
|
3284
|
-
/**
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
readonly
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
readonly store: CredentialCacheStore;
|
|
3291
|
-
readonly status: "fresh" | "expired";
|
|
3292
|
-
readonly ageMs: number;
|
|
3293
|
-
readonly expiresInMs?: number;
|
|
5035
|
+
declare function ensureHeadroom(params: {
|
|
5036
|
+
readonly paths: LayoutPaths;
|
|
5037
|
+
readonly launcherPid: number;
|
|
5038
|
+
readonly ports: EnsureHeadroomPorts;
|
|
5039
|
+
/**
|
|
5040
|
+
* The hash of the allowlist the daemon must have been started with for this launch to work, read fresh on every poll because the front door's address it contains can change while the launch waits. Given for a launch that routes a provider through headroom, whose requests come back to the front door's direct origin and are refused by a daemon that was started without it; absent for a launch that only needs Claude Code's own API, which every daemon admits.
|
|
5041
|
+
*/
|
|
5042
|
+
readonly requiredAllowlistHash?: () => string;
|
|
5043
|
+
}): {
|
|
5044
|
+
readonly socketPath: string;
|
|
3294
5045
|
};
|
|
3295
5046
|
|
|
3296
|
-
/**
|
|
3297
|
-
type
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
readonly
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
readonly
|
|
3307
|
-
readonly stdout: string;
|
|
3308
|
-
readonly stderr: string;
|
|
3309
|
-
readonly timedOut: boolean;
|
|
5047
|
+
/** The token-saving settings of the `headroom` config block, without its install and lifecycle fields (`source`, `idleShutdownMinutes`). */
|
|
5048
|
+
type HeadroomSettings = Pick<HeadroomGlobalConfig, "mode" | "targetRatio" | "ccr" | "rolloutChannel" | "interceptToolResults" | "readMaturation">;
|
|
5049
|
+
|
|
5050
|
+
/** Everything the supervisor needs to run the daemon, resolved from the global config and the filesystem before it starts. */
|
|
5051
|
+
interface HeadroomSupervisorConfig {
|
|
5052
|
+
/** The install spec as configured (`headroom.source`), already defaulted. */
|
|
5053
|
+
readonly source: string;
|
|
5054
|
+
/** `headroom.idleShutdownMinutes`, already defaulted. */
|
|
5055
|
+
readonly idleShutdownMinutes: number;
|
|
5056
|
+
/** The token-saving settings (`mode`, `targetRatio`, `ccr`, the rollout channel and its opt-ins), as configured; unset fields leave headroom on its own defaults. */
|
|
5057
|
+
readonly settings: HeadroomSettings;
|
|
3310
5058
|
}
|
|
5059
|
+
/** How the supervisor resolves the configured source against its defaults. */
|
|
5060
|
+
declare function resolveSupervisorConfig(configured: Readonly<HeadroomGlobalConfig>): HeadroomSupervisorConfig;
|
|
3311
5061
|
/**
|
|
3312
|
-
*
|
|
5062
|
+
* Every effect the supervisor performs, injected so the whole lifecycle is testable against fakes: no real process, port, clock, or HTTP call ever happens in a unit test.
|
|
3313
5063
|
*/
|
|
3314
|
-
interface
|
|
3315
|
-
|
|
3316
|
-
readonly
|
|
3317
|
-
|
|
3318
|
-
readonly
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
/**
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
readonly
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
readonly
|
|
3337
|
-
|
|
3338
|
-
readonly
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
readonly account?: string;
|
|
3344
|
-
} | {
|
|
3345
|
-
readonly kind: "literal";
|
|
3346
|
-
};
|
|
3347
|
-
/** A credential block as it is reported: its effective target and each source's summary, in order. */
|
|
3348
|
-
interface CredentialSummary {
|
|
3349
|
-
readonly target: CredentialTarget;
|
|
3350
|
-
readonly sources: readonly CredentialSourceSummary[];
|
|
3351
|
-
/** The block's cache setting when it asks for caching: how long a token is kept (absent for no expiry) and where. */
|
|
3352
|
-
readonly cache?: {
|
|
3353
|
-
readonly ttl?: string;
|
|
3354
|
-
readonly store?: string;
|
|
5064
|
+
interface SupervisorPorts {
|
|
5065
|
+
readonly fs: HeadroomFs;
|
|
5066
|
+
readonly paths: LayoutPaths;
|
|
5067
|
+
readonly ownPid: number;
|
|
5068
|
+
readonly now: () => number;
|
|
5069
|
+
/**
|
|
5070
|
+
* Waits `ms`, yielding to the event loop while it does. Deliberately NOT a synchronous Atomics.wait-style sleep: the real supervisor learns of its child's death through the ChildProcess exit event, and a blocking sleep would stop the event loop from ever delivering it (the exact failure that left an unreaped zombie answering liveness checks as alive).
|
|
5071
|
+
*/
|
|
5072
|
+
readonly sleep: (ms: number) => Promise<void>;
|
|
5073
|
+
/**
|
|
5074
|
+
* Zombie-aware liveness, and for a daemon this supervisor spawned, exit-event-backed: the implementation keeps the spawned ChildProcess handle, consumes its exit event (which is also what reaps it), and reports the pid as not running from that moment. A bare signal-0 check is not enough, because a defunct process still answers it.
|
|
5075
|
+
*/
|
|
5076
|
+
readonly isRunning: (pid: number) => boolean;
|
|
5077
|
+
/** The platform facts and owner-only checks the daemon's socket directory is prepared and verified with (see `prepareHeadroomSocket`). */
|
|
5078
|
+
readonly socketTrust: HeadroomSocketTrustPorts;
|
|
5079
|
+
/**
|
|
5080
|
+
* Starts `headroom proxy` serving on the unix socket `socketPath` (and on no TCP port) with the given allowlist, returning its pid. Output goes to the daemon log. The implementation must keep the ChildProcess handle and attach an exit listener (detaching the process is fine; unref'ing a child you still need events from is not, since without the listener nothing reaps it and it lingers as a zombie).
|
|
5081
|
+
*/
|
|
5082
|
+
readonly spawnHeadroom: (socketPath: string, allowlist: readonly string[], settings: Readonly<HeadroomSettings>) => number;
|
|
5083
|
+
/** Reads the headroom config block as it stands on disk now. The supervisor calls it every tick, so a changed `source` or setting is noticed while the daemon runs and applied by the same quiet-registry restart an allowlist change gets. */
|
|
5084
|
+
readonly readConfig: () => HeadroomSupervisorConfig;
|
|
5085
|
+
/** Stops a process the supervisor owns, escalating SIGTERM to SIGKILL on a bounded timeout (see `stopSupervisedProcess`). */
|
|
5086
|
+
readonly stopProcess: (pid: number) => void;
|
|
5087
|
+
/** True once `GET /readyz` over the unix socket succeeds. */
|
|
5088
|
+
readonly ready: (socketPath: string) => Promise<boolean>;
|
|
5089
|
+
/** Runs `uv tool install <spec>`, logging output to the daemon log. Returns ok=false with the error when `uv` is absent or the install fails. */
|
|
5090
|
+
readonly install: (spec: string) => {
|
|
5091
|
+
readonly ok: boolean;
|
|
5092
|
+
readonly error?: string;
|
|
3355
5093
|
};
|
|
5094
|
+
/** The installed `headroom --version` output, or undefined when the binary is not on PATH. */
|
|
5095
|
+
readonly headroomVersion: () => string | undefined;
|
|
5096
|
+
/** The commit the installed headroom was built from, as the install itself records it (`direct_url.json`), or undefined when it was not installed from a git source. */
|
|
5097
|
+
readonly installedCommit: () => string | undefined;
|
|
5098
|
+
readonly log: (line: string) => void;
|
|
3356
5099
|
}
|
|
3357
|
-
/**
|
|
3358
|
-
interface
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
5100
|
+
/** Options for `runSupervisor`. */
|
|
5101
|
+
interface RunSupervisorOptions {
|
|
5102
|
+
/**
|
|
5103
|
+
* Bounds the supervisor loop's iterations. The real supervisor runs until it exits on its own (idle shutdown or fatal error); a bounded run is how tests observe steady-state behaviour (drift deferral, restart-on-crash, pruning) without an infinite loop, and such a run returns `HEADROOM_SUPERVISOR_STILL_RUNNING` instead of an exit code.
|
|
5104
|
+
*/
|
|
5105
|
+
readonly tickLimit?: number;
|
|
3362
5106
|
}
|
|
5107
|
+
/**
|
|
5108
|
+
* Runs the headroom supervisor loop: install the daemon, start it, keep it alive (for crash or drift), and stop it after the configured idle period with an empty session registry. Returns the process exit code (0 for an idle shutdown, 1 for a fatal setup failure).
|
|
5109
|
+
*
|
|
5110
|
+
* Every effect flows through `ports`, so the whole loop is unit-testable with a fake clock, filesystem, and processes. The loop awaits its sleeps, which in the real implementation run on a timer: between ticks the event loop turns, the spawned child's exit event is delivered (and the child thereby reaped), and the next tick's liveness check reads the truth.
|
|
5111
|
+
*/
|
|
5112
|
+
declare function runSupervisor(initialConfig: HeadroomSupervisorConfig, ports: SupervisorPorts, options?: RunSupervisorOptions): Promise<number>;
|
|
3363
5113
|
|
|
3364
|
-
/** Raised by any operation that requires
|
|
3365
|
-
declare class
|
|
5114
|
+
/** Raised by any operation that requires an identity to already exist, when it does not. */
|
|
5115
|
+
declare class IdentityNotFoundError extends CliError {
|
|
3366
5116
|
readonly name: string;
|
|
3367
5117
|
constructor(name: string);
|
|
3368
5118
|
}
|
|
3369
|
-
/** Raised by `
|
|
3370
|
-
declare class
|
|
3371
|
-
readonly
|
|
3372
|
-
constructor(
|
|
5119
|
+
/** Raised by `addIdentity` when an identity with the given name already has an `identity.json`. */
|
|
5120
|
+
declare class IdentityAlreadyExistsError extends CliError {
|
|
5121
|
+
readonly identityName: string;
|
|
5122
|
+
constructor(identityName: string);
|
|
3373
5123
|
}
|
|
3374
|
-
/**
|
|
3375
|
-
|
|
3376
|
-
*/
|
|
3377
|
-
declare class InvalidProviderNameError extends CliError {
|
|
5124
|
+
/** Raised by `addIdentity` when `name` fails `IdentitySchema`'s own naming rule — it must start with a letter or number and may then contain letters, numbers, dots, hyphens, underscores, and at signs, so an email address names an identity directly while a *leading* `@` stays invalid (it would collide with the `@name` selector syntax's first-`@` split). */
|
|
5125
|
+
declare class InvalidIdentityNameError extends CliError {
|
|
3378
5126
|
readonly attemptedName: string;
|
|
3379
5127
|
constructor(attemptedName: string);
|
|
3380
5128
|
}
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
declare
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
declare function
|
|
3396
|
-
/**
|
|
3397
|
-
|
|
5129
|
+
declare function identityExists(paths: LayoutPaths, name: string): boolean;
|
|
5130
|
+
/** Reads and validates one identity's `identity.json`, or undefined when it does not exist. */
|
|
5131
|
+
declare function readIdentity(paths: LayoutPaths, name: string): Identity | undefined;
|
|
5132
|
+
/**
|
|
5133
|
+
* Creates a new identity: validates `name` against `IdentitySchema`'s own naming rule and writes a fresh `identity.json` with `allowAmbientCredential: false` and no `defaultConfigProfile`.
|
|
5134
|
+
*
|
|
5135
|
+
* Throws `IdentityAlreadyExistsError` if an identity with this name already has an `identity.json` — `add` never silently overwrites an existing identity. Throws `InvalidIdentityNameError` when `name` fails `IdentitySchema`'s naming rule, rather than letting the underlying `ZodError` escape as an unhandled crash.
|
|
5136
|
+
*/
|
|
5137
|
+
declare function addIdentity(paths: LayoutPaths, name: string): Identity;
|
|
5138
|
+
/**
|
|
5139
|
+
* Persists `name` as the active identity, written atomically as plain text (not JSON — this file is read by `decideIdentity` in `src/launcher/identity.ts` via a simple UTF-8 read-and-trim, matching the README's documented `~/.agent-shim/active-identity` file).
|
|
5140
|
+
*
|
|
5141
|
+
* `name` may be a `pool:<name>` selector, which makes launches pick a member of that pool. Throws `IdentityNotFoundError` when no identity with this name exists yet, and `PoolNotFoundError` for a pool that is not defined: selecting either would silently persist a name nothing else can ever load.
|
|
5142
|
+
*/
|
|
5143
|
+
declare function useIdentity(paths: LayoutPaths, name: string): void;
|
|
5144
|
+
/** Reads the persisted active-identity file, or undefined when none is set. */
|
|
5145
|
+
declare function readActiveIdentity(paths: LayoutPaths): string | undefined;
|
|
5146
|
+
/**
|
|
5147
|
+
* Whether a directory name directly under `identitiesDir` names an actual identity, rather than one of agent-shim's own farm directories.
|
|
5148
|
+
*
|
|
5149
|
+
* `IdentitySchema` requires an identity name to start with a letter or digit, so a leading `.` can only be a resync's own bookkeeping: a `.<identity>.scratch.<suffix>` tree still being built, or a `.<identity>.previous.<suffix>` superseded farm retained for `agent-shim identity resolve-conflicts`. Neither is an identity, and neither should be reported as a broken one for lacking an `identity.json` a resync never put there.
|
|
5150
|
+
*/
|
|
5151
|
+
declare function isIdentityDirectoryName(name: string): boolean;
|
|
5152
|
+
/** One identity as reported by `listIdentities`, whose `identity.json` parsed and validated cleanly. */
|
|
5153
|
+
interface IdentityListEntry {
|
|
3398
5154
|
readonly name: string;
|
|
3399
|
-
readonly
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
declare function listProviders(paths: LayoutPaths): readonly ProviderListEntry[];
|
|
3403
|
-
/** The credential targets a provider may use. */
|
|
3404
|
-
type ProviderCredentialTarget = (typeof PROVIDER_CREDENTIAL_TARGETS)[number];
|
|
3405
|
-
/** The kinds of provider. */
|
|
3406
|
-
type ProviderKind = (typeof PROVIDER_KINDS)[number];
|
|
3407
|
-
/** Where a provider sends its sessions, for display: an `http` provider's base URL, or the front door for a codex provider (whose address exists only at launch). */
|
|
3408
|
-
declare function describeProviderEndpoint(provider: Provider): string;
|
|
3409
|
-
/** Everything `addProvider` writes into a fresh provider file. `baseUrl` is required for an `http` provider and refused for a codex one; `codex` applies only to a codex provider. */
|
|
3410
|
-
interface AddProviderInput {
|
|
3411
|
-
readonly kind?: ProviderKind;
|
|
3412
|
-
readonly displayName: string;
|
|
3413
|
-
readonly baseUrl?: string;
|
|
3414
|
-
readonly sources: readonly CredentialSource[];
|
|
3415
|
-
readonly target?: ProviderCredentialTarget;
|
|
3416
|
-
readonly env?: Readonly<Record<string, string>>;
|
|
3417
|
-
readonly codex?: CodexProviderConfig;
|
|
5155
|
+
readonly identity: Identity;
|
|
5156
|
+
readonly isActive: boolean;
|
|
5157
|
+
readonly problem?: never;
|
|
3418
5158
|
}
|
|
3419
|
-
/**
|
|
3420
|
-
|
|
3421
|
-
|
|
5159
|
+
/** One identity whose `identity.json` is present but unreadable — malformed JSON, or valid JSON this version's `IdentitySchema` rejects. `problem` carries the reason, already flattened onto a single line. */
|
|
5160
|
+
interface UnreadableIdentityListEntry {
|
|
5161
|
+
readonly name: string;
|
|
5162
|
+
readonly identity?: never;
|
|
5163
|
+
readonly isActive: boolean;
|
|
5164
|
+
readonly problem: string;
|
|
3422
5165
|
}
|
|
5166
|
+
/** Either shape `listIdentities` can report, discriminated by which of `identity`/`problem` is present rather than by a tag field — the two are never simultaneously satisfiable. */
|
|
5167
|
+
type IdentityListing = IdentityListEntry | UnreadableIdentityListEntry;
|
|
5168
|
+
/**
|
|
5169
|
+
* Lists every identity under `identitiesDir`, marking which one (if any) is currently active.
|
|
5170
|
+
*
|
|
5171
|
+
* One identity whose `identity.json` cannot be read is reported as its own `UnreadableIdentityListEntry` rather than aborting the whole listing. A single bad file blocking `identity list` outright is exactly the failure mode that hides every *other* identity from view at the moment the user most needs to see them — and the file need not even be corrupt to land here, since a name written by a newer agent-shim whose naming rule has since widened is rejected outright by an older binary's own copy of `IdentitySchema`.
|
|
5172
|
+
*/
|
|
5173
|
+
declare function listIdentities(paths: LayoutPaths): readonly IdentityListing[];
|
|
3423
5174
|
/**
|
|
3424
|
-
*
|
|
5175
|
+
* Sets `identity`'s `defaultConfigProfile` field, or clears it when `profileName` is undefined. Throws `IdentityNotFoundError` when the identity does not exist. Whether the profile exists is the caller's concern: `identity set --default-profile` checks it first.
|
|
3425
5176
|
*/
|
|
3426
|
-
declare function
|
|
5177
|
+
declare function setDefaultConfigProfile(paths: LayoutPaths, identityName: string, profileName: string | undefined): Identity;
|
|
3427
5178
|
/**
|
|
3428
|
-
*
|
|
5179
|
+
* Patches `identity`'s `allowAmbientCredential` field. Throws `IdentityNotFoundError` when the identity does not exist.
|
|
3429
5180
|
*/
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
5181
|
+
declare function setAllowAmbientCredential(paths: LayoutPaths, identityName: string, allow: boolean): Identity;
|
|
5182
|
+
/** The change `setIdentityCredential` makes: new sources and/or a new target for the credential block, or `false` to remove the block and return the identity to its stored login. */
|
|
5183
|
+
type IdentityCredentialChange = {
|
|
3433
5184
|
readonly sources?: readonly CredentialSource[];
|
|
3434
|
-
readonly target?:
|
|
3435
|
-
/** A new cache block, or false to remove it; undefined leaves the existing one. */
|
|
5185
|
+
readonly target?: CredentialTarget;
|
|
3436
5186
|
readonly cache?: CredentialCache | false;
|
|
3437
|
-
|
|
3438
|
-
readonly unsetEnv?: readonly string[];
|
|
3439
|
-
/** Merged over a codex provider's existing settings: a field given here replaces that field, and `models` entries merge per tier. */
|
|
3440
|
-
readonly codex?: CodexProviderConfig;
|
|
3441
|
-
}
|
|
5187
|
+
} | false;
|
|
3442
5188
|
/**
|
|
3443
|
-
*
|
|
5189
|
+
* Sets, changes or removes `identityName`'s credential block. New `sources` replace the whole ordered list (the order is the meaning); a `target` alone keeps the existing sources, and so needs a credential block to exist already. Throws `IdentityNotFoundError` when the identity does not exist, and `UsageError` when only a target is given for an identity with no credential yet.
|
|
3444
5190
|
*/
|
|
3445
|
-
declare function
|
|
3446
|
-
/**
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
declare class PoolNotFoundError extends CliError {
|
|
3451
|
-
readonly poolName: string;
|
|
3452
|
-
constructor(poolName: string);
|
|
3453
|
-
}
|
|
3454
|
-
/** The pools defined in `~/.agent-shim/config.json`, by name. */
|
|
3455
|
-
declare function readPools(paths: LayoutPaths): Readonly<Record<string, Pool>>;
|
|
3456
|
-
/** The pool named `name`; throws `PoolNotFoundError` when none is defined. */
|
|
3457
|
-
declare function requirePool(paths: LayoutPaths, name: string): Pool;
|
|
3458
|
-
/** Defines a new pool. Throws `InvalidPoolNameError` for a name `PoolNameSchema` rejects and `PoolAlreadyExistsError` for one already defined. */
|
|
3459
|
-
declare function addPool(paths: LayoutPaths, name: string, identities: readonly string[]): Pool;
|
|
3460
|
-
/** Replaces an existing pool's members. Throws `PoolNotFoundError` when it is not defined. */
|
|
3461
|
-
declare function setPool(paths: LayoutPaths, name: string, identities: readonly string[]): Pool;
|
|
3462
|
-
/** Removes a pool. Throws `PoolNotFoundError` when it is not defined. Anything that selected it (an active-identity file, a directory rule) is left for `doctor` to report, as with a removed identity. */
|
|
3463
|
-
declare function removePool(paths: LayoutPaths, name: string): void;
|
|
5191
|
+
declare function setIdentityCredential(paths: LayoutPaths, identityName: string, change: IdentityCredentialChange): Identity;
|
|
5192
|
+
/**
|
|
5193
|
+
* Deletes identity `name` entirely: its directory under `identitiesDir` (the farm, its `identity.json`, and whatever that farm holds unshared, credentials included), its resync lock, any scratch or superseded farm a resync left behind, and the active-identity selection when it names this identity. Data shared into `~/.claude` stays there, since the farm only ever symlinks to it. Throws `IdentityNotFoundError` when the identity does not exist.
|
|
5194
|
+
*/
|
|
5195
|
+
declare function removeIdentity(paths: LayoutPaths, name: string): void;
|
|
3464
5196
|
|
|
3465
|
-
/** Raised by
|
|
3466
|
-
declare class
|
|
3467
|
-
readonly
|
|
3468
|
-
constructor(
|
|
3469
|
-
}
|
|
3470
|
-
/** Raised by `addDirectoryRule` when neither `--config-profile` nor `--identity` is given, and by `updateDirectoryRule` when an update would leave a rule that sets nothing at all: a rule that pins and overrides nothing would do nothing. */
|
|
3471
|
-
declare class DirectoryRuleMissingTargetError extends CliError {
|
|
3472
|
-
constructor();
|
|
5197
|
+
/** Raised by any operation that requires a configuration profile to already exist, when it does not. */
|
|
5198
|
+
declare class ProfileNotFoundError extends CliError {
|
|
5199
|
+
readonly profileName: string;
|
|
5200
|
+
constructor(profileName: string);
|
|
3473
5201
|
}
|
|
3474
|
-
/** Raised by `
|
|
3475
|
-
declare class
|
|
3476
|
-
readonly
|
|
3477
|
-
constructor(
|
|
5202
|
+
/** Raised by `createProfile` (`profile add`) when a profile with the given name already has a file. */
|
|
5203
|
+
declare class ProfileAlreadyExistsError extends CliError {
|
|
5204
|
+
readonly profileName: string;
|
|
5205
|
+
constructor(profileName: string);
|
|
3478
5206
|
}
|
|
3479
|
-
/**
|
|
3480
|
-
declare
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
/** Lists every directory rule, in file order. */
|
|
3484
|
-
declare function listDirectoryRules(paths: LayoutPaths): readonly DirectoryRule[];
|
|
3485
|
-
/** Inputs to `addDirectoryRule` beyond the path itself. */
|
|
3486
|
-
interface AddDirectoryRuleOptions {
|
|
3487
|
-
readonly configProfile?: string;
|
|
3488
|
-
readonly identity?: string;
|
|
5207
|
+
/** Raised when a `--category` patch names something other than one of the four overridable categories (e.g. `secret`, or a typo). */
|
|
5208
|
+
declare class InvalidCategoryNameError extends CliError {
|
|
5209
|
+
readonly categoryName: string;
|
|
5210
|
+
constructor(categoryName: string);
|
|
3489
5211
|
}
|
|
5212
|
+
/** True when a profile file exists for `name`, regardless of whether it validates. */
|
|
5213
|
+
declare function profileExists(paths: LayoutPaths, name: string): boolean;
|
|
5214
|
+
/** Reads and validates one configuration profile, or undefined when it does not exist. */
|
|
5215
|
+
declare function readProfile(paths: LayoutPaths, name: string): ConfigProfile | undefined;
|
|
3490
5216
|
/**
|
|
3491
|
-
*
|
|
5217
|
+
* Creates a new configuration profile, empty apart from the optional `extends` list and description. Throws `ProfileAlreadyExistsError` if a profile with this name already has a file, and `ConfigValidationError` when the result fails `ConfigProfileSchema` (e.g. an empty `--extends ""` name), rather than letting the underlying `ZodError` escape as an unhandled crash.
|
|
3492
5218
|
*/
|
|
3493
|
-
declare function
|
|
3494
|
-
/**
|
|
3495
|
-
interface
|
|
3496
|
-
readonly
|
|
3497
|
-
readonly
|
|
5219
|
+
declare function createProfile(paths: LayoutPaths, name: string, extendsList?: readonly string[], description?: string): ConfigProfile;
|
|
5220
|
+
/** One profile as reported by `listProfiles`. */
|
|
5221
|
+
interface ProfileListEntry {
|
|
5222
|
+
readonly name: string;
|
|
5223
|
+
readonly profile: ConfigProfile;
|
|
3498
5224
|
}
|
|
5225
|
+
/** Lists every configuration profile under `configProfilesDir` that has a valid `<name>.json`. */
|
|
5226
|
+
declare function listProfiles(paths: LayoutPaths): readonly ProfileListEntry[];
|
|
5227
|
+
/** Reads the user-global `~/.agent-shim/config.json`, or undefined when it does not exist. */
|
|
5228
|
+
declare function readGlobalConfig(paths: LayoutPaths): GlobalConfig | undefined;
|
|
5229
|
+
/** Sets the user-global default configuration profile in `~/.agent-shim/config.json`, creating the file if it doesn't exist yet. Whether the profile exists is the caller's concern: `profile use` checks it first. */
|
|
5230
|
+
declare function setGlobalDefaultProfile(paths: LayoutPaths, name: string): GlobalConfig;
|
|
3499
5231
|
/**
|
|
3500
|
-
*
|
|
5232
|
+
* Merges `patch` (from one or more `--category cat=bool` flags) into `profile`'s own `categories` object and writes it back.
|
|
5233
|
+
*
|
|
5234
|
+
* Throws `InvalidCategoryNameError` for any key that isn't one of the four overridable categories — `secret` can never be toggled by any configuration layer, this included.
|
|
3501
5235
|
*/
|
|
3502
|
-
declare function
|
|
3503
|
-
/** Removes the directory rule for `rulePath`. Throws `DirectoryRuleNotFoundError` when no rule matches that exact path. */
|
|
3504
|
-
declare function removeDirectoryRule(paths: LayoutPaths, rulePath: string): void;
|
|
3505
|
-
|
|
3506
|
-
/** Where a pinned Claude Code version came from, strongest first: the launch's own flag, then the environment, then the cascade. */
|
|
3507
|
-
type ClaudeVersionSource = "flag" | "environment" | "cascade";
|
|
3508
|
-
/** The pinned version a launch runs, and which of the three forms named it. */
|
|
3509
|
-
interface PinnedClaudeVersion {
|
|
3510
|
-
readonly version: string;
|
|
3511
|
-
readonly source: ClaudeVersionSource;
|
|
3512
|
-
}
|
|
3513
|
-
|
|
3514
|
-
/** Which precedence rule produced an identity decision. */
|
|
3515
|
-
type IdentityDecisionSource =
|
|
3516
|
-
/** `CLAUDE_CONFIG_DIR` was already set: identity resolution is skipped entirely and the real binary uses whatever it already points to. */
|
|
3517
|
-
"config-dir-escape-hatch"
|
|
3518
|
-
/** A leading `@name` argv[0] positional, or its explicit form `--identity <name>`. */
|
|
3519
|
-
| "argv"
|
|
3520
|
-
/** The `AGENT_SHIM_IDENTITY` environment variable. */
|
|
3521
|
-
| "env"
|
|
3522
|
-
/** A directory rule pinning an identity to the current path. */
|
|
3523
|
-
| "directory-pin"
|
|
3524
|
-
/** The persisted `~/.agent-shim/active-identity` file. */
|
|
3525
|
-
| "active-identity-file"
|
|
3526
|
-
/** Nothing resolved an identity at all — a bare launch with no active identity. */
|
|
3527
|
-
| "none";
|
|
3528
|
-
/** Which precedence rule produced a configuration-profile decision. */
|
|
3529
|
-
type ConfigProfileDecisionSource =
|
|
3530
|
-
/** An explicit `--config-profile` CLI flag. */
|
|
3531
|
-
"cli-flag"
|
|
3532
|
-
/** The `AGENT_SHIM_CONFIG_PROFILE` environment variable. */
|
|
3533
|
-
| "env"
|
|
3534
|
-
/** A directory rule's `configProfile` selection for `$PWD`. */
|
|
3535
|
-
| "directory-rule"
|
|
3536
|
-
/** The active identity's own declared `defaultConfigProfile`. */
|
|
3537
|
-
| "identity-default"
|
|
3538
|
-
/** The user-global `~/.agent-shim/config.json` default. */
|
|
3539
|
-
| "global-default"
|
|
3540
|
-
/** Nothing resolved a configuration profile at all. */
|
|
3541
|
-
| "none";
|
|
3542
|
-
|
|
5236
|
+
declare function setProfileCategories(paths: LayoutPaths, name: string, patch: Readonly<Record<string, boolean>>): ConfigProfile;
|
|
3543
5237
|
/**
|
|
3544
|
-
*
|
|
3545
|
-
*
|
|
3546
|
-
* The encoding collapses the *entire* non-alphanumeric character class to `-`, not just the path separator: `.`, `_`, ` `, `@`, and `/` all become `-`, while letters and digits pass through with their case preserved. This was confirmed against a real installation's project directories, not assumed from the one `/`-becomes-`-` sample the README quotes.
|
|
5238
|
+
* Merges `patch` (from one or more `--entry "path"=bool` flags) into `profile`'s own `entries` object and writes it back.
|
|
3547
5239
|
*
|
|
3548
|
-
*
|
|
5240
|
+
* Key validity (the `<category>/<real-relative-path>` prefix requirement) is enforced by `ConfigProfileSchema`'s own `EntriesSchema` at write time — an invalid key surfaces as the usual `ConfigValidationError`.
|
|
3549
5241
|
*/
|
|
5242
|
+
declare function setProfileEntries(paths: LayoutPaths, name: string, patch: Readonly<Record<string, boolean>>): ConfigProfile;
|
|
5243
|
+
/**
|
|
5244
|
+
* Merges `patch` into `profile`'s own `launch` object and writes it back. A key present in `patch` with the value `undefined` removes that setting outright (a `--no-launch-provider`, say) rather than overwriting it, and a `launch` object left with no settings is removed too.
|
|
5245
|
+
*/
|
|
5246
|
+
declare function setProfileLaunchFlags(paths: LayoutPaths, name: string, patch: Readonly<LaunchFlags>): ConfigProfile;
|
|
5247
|
+
/** Replaces `profile`'s own `extends` list and/or description; an empty list or an undefined description removes the field. */
|
|
5248
|
+
declare function setProfileMetadata(paths: LayoutPaths, name: string, patch: Readonly<{
|
|
5249
|
+
extends?: readonly string[];
|
|
5250
|
+
description?: string | false;
|
|
5251
|
+
}>): ConfigProfile;
|
|
5252
|
+
/** Deletes a configuration profile's file. Throws `ProfileNotFoundError` when it does not exist. Nothing that references it by name is rewritten; `agent-shim doctor` reports any identity default, directory rule or `extends` left pointing at it. */
|
|
5253
|
+
declare function removeProfile(paths: LayoutPaths, name: string): void;
|
|
3550
5254
|
|
|
3551
|
-
/**
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
/** Two different patterns in the same configuration encode to the identical form. */
|
|
3556
|
-
| "collides-with-sibling-pattern";
|
|
3557
|
-
/** One reported ambiguity in a `history/projects/` pattern. */
|
|
3558
|
-
interface EncodingAmbiguity {
|
|
3559
|
-
readonly fragment: string;
|
|
3560
|
-
readonly encoded: string;
|
|
3561
|
-
readonly reason: EncodingAmbiguityReason;
|
|
3562
|
-
readonly detail: string;
|
|
3563
|
-
}
|
|
3564
|
-
|
|
3565
|
-
/** The result of looking up the macOS Keychain service name Claude Code is actually using for one identity's farm. */
|
|
3566
|
-
interface KeychainLookupResult {
|
|
3567
|
-
readonly checked: true;
|
|
3568
|
-
readonly found: boolean;
|
|
3569
|
-
readonly serviceName?: string;
|
|
3570
|
-
readonly note: string;
|
|
5255
|
+
/** Raised by any operation that requires a provider to already exist, when it does not. */
|
|
5256
|
+
declare class ProviderNotFoundError extends CliError {
|
|
5257
|
+
readonly name: string;
|
|
5258
|
+
constructor(name: string);
|
|
3571
5259
|
}
|
|
3572
|
-
/**
|
|
3573
|
-
|
|
3574
|
-
readonly
|
|
3575
|
-
|
|
3576
|
-
readonly hookEventNames: readonly string[];
|
|
3577
|
-
readonly hookCommandCount: number;
|
|
5260
|
+
/** Raised by `addProvider` when a provider with the given name already has a file. */
|
|
5261
|
+
declare class ProviderAlreadyExistsError extends CliError {
|
|
5262
|
+
readonly providerName: string;
|
|
5263
|
+
constructor(providerName: string);
|
|
3578
5264
|
}
|
|
3579
|
-
/** The provider the cascade selects for this directory, as the wiring layer loaded it: its definition, or why it could not be used (no such provider, an invalid or old-format file). */
|
|
3580
|
-
type CheckProviderInput = {
|
|
3581
|
-
readonly name: string;
|
|
3582
|
-
readonly definition: Provider;
|
|
3583
|
-
readonly problem?: never;
|
|
3584
|
-
} | {
|
|
3585
|
-
readonly name: string;
|
|
3586
|
-
readonly definition?: never;
|
|
3587
|
-
readonly problem: string;
|
|
3588
|
-
};
|
|
3589
5265
|
/**
|
|
3590
|
-
*
|
|
5266
|
+
* Raised by `addProvider` when `name` fails the provider naming rule: the same rule `IdentitySchema` applies to identity names (start with a letter or number, then letters, numbers, dots, hyphens, underscores, and at signs). Keeping the two rules identical means a name that works for one works for the other, and neither vocabulary can ever produce a path segment that escapes `providers/` or `identities/`.
|
|
3591
5267
|
*/
|
|
3592
|
-
|
|
3593
|
-
readonly
|
|
3594
|
-
|
|
3595
|
-
readonly name: string;
|
|
3596
|
-
readonly credential?: CredentialSummary;
|
|
3597
|
-
readonly problem?: string;
|
|
3598
|
-
readonly cached?: CachedCredentialState;
|
|
3599
|
-
};
|
|
3600
|
-
readonly identity?: CredentialSummary;
|
|
3601
|
-
/** What the identity's own credential cache holds, when its block caches and the cache could be read. */
|
|
3602
|
-
readonly identityCached?: CachedCredentialState;
|
|
3603
|
-
}
|
|
3604
|
-
/** Inputs to `runCheck` — everything already loaded/injected, exactly like the resolver core and the launcher: nothing in this function touches a real filesystem, git repository, clock, or environment itself. */
|
|
3605
|
-
interface RunCheckParams {
|
|
3606
|
-
readonly cwd: string;
|
|
3607
|
-
readonly home: string;
|
|
3608
|
-
readonly claudeHome: string;
|
|
3609
|
-
readonly env: Readonly<Record<string, string | undefined>>;
|
|
3610
|
-
readonly branch?: string;
|
|
3611
|
-
readonly branchDetached?: boolean;
|
|
3612
|
-
readonly nowMs: number;
|
|
3613
|
-
/** Used only to build the fact manifest by reading the canonical `~/.claude` tree — `runCheck` never mutates the farm and never spawns anything. */
|
|
3614
|
-
readonly farmFs: FarmFs;
|
|
3615
|
-
readonly cascade: CascadeInput;
|
|
3616
|
-
readonly classification: {
|
|
3617
|
-
readonly defaults: CategoryClassification;
|
|
3618
|
-
readonly overlay?: CategoryClassificationOverlay;
|
|
3619
|
-
};
|
|
3620
|
-
readonly identityName?: string;
|
|
3621
|
-
readonly identitySource: IdentityDecisionSource;
|
|
3622
|
-
/** The pool the launch selected and how it ranks right now, when it named a pool instead of an identity; `identityName` is then the member it would pick. */
|
|
3623
|
-
readonly poolPick?: PoolPickReport;
|
|
3624
|
-
readonly configProfileName?: string;
|
|
3625
|
-
readonly configProfileSource: ConfigProfileDecisionSource;
|
|
3626
|
-
/** The resolved identity's own `identity.json`, when one was found. */
|
|
3627
|
-
readonly identity?: Identity;
|
|
3628
|
-
/** Raw `settings.json`/`settings.local.json` contents, keyed by filename, undefined when a file does not exist. */
|
|
3629
|
-
readonly settingsFiles: Readonly<Record<string, string | undefined>>;
|
|
3630
|
-
/** Runs `security find-generic-password` for the Keychain diagnostic. Omit to skip that diagnostic entirely (e.g. off macOS, or when no identity/farm root is known). */
|
|
3631
|
-
readonly run?: RunPort;
|
|
3632
|
-
/** The identity's own farm root — `security`'s lookup account. Required alongside `run` for the Keychain diagnostic to run at all. */
|
|
3633
|
-
readonly farmRoot?: string;
|
|
3634
|
-
/** `process.platform` in real use; the Keychain diagnostic only ever runs when this is `"darwin"`. */
|
|
3635
|
-
readonly platform: string;
|
|
3636
|
-
/** The provider a launch here would route through (`launch.provider` in the cascade), when one is selected. */
|
|
3637
|
-
readonly provider?: CheckProviderInput;
|
|
3638
|
-
/** The Claude Code versions installed here, oldest first. Omit to leave the Claude Code version out of the report; with it, `check` says which version a launch here runs and whether a pin is installed. */
|
|
3639
|
-
readonly installedClaudeVersions?: readonly string[];
|
|
3640
|
-
/** Where cached credentials live. Omit to skip reporting a credential cache's age; with it, a block that caches reports whether it holds an entry, how old it is and whether it has expired, never the token. */
|
|
3641
|
-
readonly credentialCache?: CredentialCacheEnv;
|
|
5268
|
+
declare class InvalidProviderNameError extends CliError {
|
|
5269
|
+
readonly attemptedName: string;
|
|
5270
|
+
constructor(attemptedName: string);
|
|
3642
5271
|
}
|
|
3643
|
-
/**
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
readonly
|
|
3648
|
-
readonly
|
|
3649
|
-
readonly configProfileSource: ConfigProfileDecisionSource;
|
|
3650
|
-
readonly resolved: ResolvedState;
|
|
3651
|
-
readonly decisionLines: readonly string[];
|
|
3652
|
-
readonly projectEncodingAmbiguities: readonly EncodingAmbiguity[];
|
|
3653
|
-
readonly ambientCredential: AmbientCredentialGuardResult;
|
|
3654
|
-
readonly keychain?: KeychainLookupResult;
|
|
3655
|
-
readonly settingsExposure: readonly SettingsExposureReport[];
|
|
3656
|
-
readonly credential: CredentialReport;
|
|
3657
|
-
/** The Claude Code version a launch here would run, when the installed versions were given. */
|
|
3658
|
-
readonly claudeVersion?: ClaudeVersionReport;
|
|
5272
|
+
/** True when a provider file exists for `name`, regardless of whether it validates. */
|
|
5273
|
+
declare function providerExists(paths: LayoutPaths, name: string): boolean;
|
|
5274
|
+
/** What converting one old-format provider file involves: the old fields it uses, and the whole file rewritten in the current format. */
|
|
5275
|
+
interface LegacyProviderConversion {
|
|
5276
|
+
readonly fields: readonly string[];
|
|
5277
|
+
readonly replacement: Record<string, unknown>;
|
|
3659
5278
|
}
|
|
3660
|
-
/**
|
|
3661
|
-
|
|
3662
|
-
readonly
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
5279
|
+
/** Raised when a provider file is still in the format before the credential block, naming the old fields and giving the exact replacement. */
|
|
5280
|
+
declare class LegacyProviderFileError extends CliError {
|
|
5281
|
+
readonly filePath: string;
|
|
5282
|
+
readonly conversion: LegacyProviderConversion;
|
|
5283
|
+
constructor(filePath: string, conversion: LegacyProviderConversion);
|
|
5284
|
+
}
|
|
5285
|
+
/** Reads and validates one provider definition, or undefined when it does not exist. */
|
|
5286
|
+
declare function readProvider(paths: LayoutPaths, name: string): Provider | undefined;
|
|
5287
|
+
/** One provider definition as reported by `listProviders`. */
|
|
5288
|
+
interface ProviderListEntry {
|
|
5289
|
+
readonly name: string;
|
|
5290
|
+
readonly provider: Provider;
|
|
5291
|
+
}
|
|
5292
|
+
/** Lists every provider under `providersDir` that has a valid `<name>.json`. A file that fails validation is skipped here; `provider list` is the place a broken definition gets surfaced, not a launch. */
|
|
5293
|
+
declare function listProviders(paths: LayoutPaths): readonly ProviderListEntry[];
|
|
5294
|
+
/** The credential targets a provider may use. */
|
|
5295
|
+
type ProviderCredentialTarget = (typeof PROVIDER_CREDENTIAL_TARGETS)[number];
|
|
5296
|
+
/** The kinds of provider. */
|
|
5297
|
+
type ProviderKind = (typeof PROVIDER_KINDS)[number];
|
|
5298
|
+
/** Where a provider sends its sessions, for display: an `http` provider's base URL, or the front door for a codex provider (whose address exists only at launch). */
|
|
5299
|
+
declare function describeProviderEndpoint(provider: Provider): string;
|
|
5300
|
+
/** Everything `addProvider` writes into a fresh provider file. `baseUrl` is required for an `http` provider and refused for a codex one; `codex` applies only to a codex provider. */
|
|
5301
|
+
interface AddProviderInput {
|
|
5302
|
+
readonly kind?: ProviderKind;
|
|
5303
|
+
readonly displayName: string;
|
|
5304
|
+
readonly baseUrl?: string;
|
|
5305
|
+
readonly sources: readonly CredentialSource[];
|
|
5306
|
+
readonly target?: ProviderCredentialTarget;
|
|
5307
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
5308
|
+
readonly codex?: CodexProviderConfig;
|
|
5309
|
+
}
|
|
5310
|
+
/** Raised when a provider option does not fit the provider's kind: a base URL for a codex provider, a missing one for an http provider, or codex settings for an http provider. */
|
|
5311
|
+
declare class ProviderKindMismatchError extends UsageError {
|
|
5312
|
+
constructor(message: string);
|
|
3667
5313
|
}
|
|
3668
5314
|
/**
|
|
3669
|
-
*
|
|
3670
|
-
*
|
|
3671
|
-
* Deliberately reuses the same cascade machinery a real launch uses — `resolveDecisions` and `buildEntryFacts` — rather than reimplementing any part of resolution. The one thing this function never does that a launch does is touch the farm or spawn anything: it only reads the canonical `~/.claude` tree to build the fact manifest resolution needs, and every other input (cascade, classification, settings file contents, the Keychain lookup) is handed in already loaded.
|
|
3672
|
-
*/
|
|
3673
|
-
declare function runCheck(params: RunCheckParams): CheckReport;
|
|
3674
|
-
/** Renders a full `CheckReport` as plain text lines, in the order `agent-shim check` prints them. */
|
|
3675
|
-
declare function formatCheckReport(report: CheckReport): string[];
|
|
3676
|
-
/**
|
|
3677
|
-
* The `check --json` form of a report: every field the text form prints, as plain data (no `Map`s, no compiled matchers), so a script can read the same verdicts a person would.
|
|
5315
|
+
* Creates a new provider definition. Throws `ProviderAlreadyExistsError` when a provider with this name already has a file, `InvalidProviderNameError` when `name` fails the naming rule, and `ConfigValidationError` when the assembled definition fails `ProviderSchema` (e.g. a `baseUrl` that is not a URL) rather than letting the underlying `ZodError` escape as an unhandled crash.
|
|
3678
5316
|
*/
|
|
3679
|
-
declare function
|
|
5317
|
+
declare function addProvider(paths: LayoutPaths, name: string, input: AddProviderInput): Provider;
|
|
3680
5318
|
/**
|
|
3681
|
-
*
|
|
5319
|
+
* The fields `updateProvider` changes. `sources` replaces the whole ordered source list (a list is set, not patched, since its order is its meaning); `target` changes where the token goes and keeps the sources. `env` entries merge over the existing ones and `unsetEnv` keys are then deleted.
|
|
3682
5320
|
*/
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
readonly
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
readonly
|
|
3691
|
-
readonly
|
|
5321
|
+
interface UpdateProviderInput {
|
|
5322
|
+
readonly displayName?: string;
|
|
5323
|
+
readonly baseUrl?: string;
|
|
5324
|
+
readonly sources?: readonly CredentialSource[];
|
|
5325
|
+
readonly target?: ProviderCredentialTarget;
|
|
5326
|
+
/** A new cache block, or false to remove it; undefined leaves the existing one. */
|
|
5327
|
+
readonly cache?: CredentialCache | false;
|
|
5328
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
5329
|
+
readonly unsetEnv?: readonly string[];
|
|
5330
|
+
/** Merged over a codex provider's existing settings: a field given here replaces that field, and `models` entries merge per tier. */
|
|
5331
|
+
readonly codex?: CodexProviderConfig;
|
|
3692
5332
|
}
|
|
3693
5333
|
/**
|
|
3694
|
-
*
|
|
5334
|
+
* Updates an existing provider definition in place. Throws `ProviderNotFoundError` when it does not exist, and `ConfigValidationError` when the updated definition fails `ProviderSchema`, leaving the file untouched.
|
|
3695
5335
|
*/
|
|
3696
|
-
declare function
|
|
3697
|
-
|
|
3698
|
-
declare
|
|
3699
|
-
targetPath: z.ZodString;
|
|
3700
|
-
method: z.ZodEnum<{
|
|
3701
|
-
hardlink: "hardlink";
|
|
3702
|
-
copy: "copy";
|
|
3703
|
-
}>;
|
|
3704
|
-
installedAtMs: z.ZodNumber;
|
|
3705
|
-
}, z.core.$strict>;
|
|
3706
|
-
type ClaudeShimState = z.infer<typeof ClaudeShimStateSchema>;
|
|
3707
|
-
type PathShadowStatus = {
|
|
3708
|
-
readonly status: "ok";
|
|
3709
|
-
} | {
|
|
3710
|
-
readonly status: "not-on-path";
|
|
3711
|
-
} | {
|
|
3712
|
-
readonly status: "shadowed";
|
|
3713
|
-
readonly by: string;
|
|
3714
|
-
};
|
|
5336
|
+
declare function updateProvider(paths: LayoutPaths, name: string, input: UpdateProviderInput): Provider;
|
|
5337
|
+
/** Deletes a provider definition. Throws `ProviderNotFoundError` when it does not exist. */
|
|
5338
|
+
declare function removeProvider(paths: LayoutPaths, name: string): void;
|
|
3715
5339
|
|
|
3716
|
-
/**
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
/** Which strategy found it. */
|
|
3721
|
-
source: "versions-dir" | "path-fallback";
|
|
3722
|
-
/** The version string, when discovered via the versions directory. */
|
|
3723
|
-
version?: string;
|
|
3724
|
-
}
|
|
3725
|
-
/** What a launch asks binary discovery for: nothing (the highest installed version) or an exact version. */
|
|
3726
|
-
interface ClaudeBinaryRequest {
|
|
3727
|
-
readonly version?: string;
|
|
5340
|
+
/** Raised when a command names a pool that is not defined in the global config. */
|
|
5341
|
+
declare class PoolNotFoundError extends CliError {
|
|
5342
|
+
readonly poolName: string;
|
|
5343
|
+
constructor(poolName: string);
|
|
3728
5344
|
}
|
|
3729
|
-
/**
|
|
3730
|
-
|
|
5345
|
+
/** The pools defined in `~/.agent-shim/config.json`, by name. */
|
|
5346
|
+
declare function readPools(paths: LayoutPaths): Readonly<Record<string, Pool>>;
|
|
5347
|
+
/** The pool named `name`; throws `PoolNotFoundError` when none is defined. */
|
|
5348
|
+
declare function requirePool(paths: LayoutPaths, name: string): Pool;
|
|
5349
|
+
/** Defines a new pool. Throws `InvalidPoolNameError` for a name `PoolNameSchema` rejects and `PoolAlreadyExistsError` for one already defined. */
|
|
5350
|
+
declare function addPool(paths: LayoutPaths, name: string, identities: readonly string[]): Pool;
|
|
5351
|
+
/** Replaces an existing pool's members. Throws `PoolNotFoundError` when it is not defined. */
|
|
5352
|
+
declare function setPool(paths: LayoutPaths, name: string, identities: readonly string[]): Pool;
|
|
5353
|
+
/** Removes a pool. Throws `PoolNotFoundError` when it is not defined. Anything that selected it (an active-identity file, a directory rule) is left for `doctor` to report, as with a removed identity. */
|
|
5354
|
+
declare function removePool(paths: LayoutPaths, name: string): void;
|
|
3731
5355
|
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
readonly section: DoctorSection;
|
|
3737
|
-
readonly subject?: string;
|
|
3738
|
-
readonly severity: DoctorSeverity;
|
|
3739
|
-
readonly message: string;
|
|
3740
|
-
}
|
|
3741
|
-
/** The full result of `runDoctor`. `ok` is false iff any finding is a `fail` — a `warn` never fails the report on its own. */
|
|
3742
|
-
interface DoctorReport {
|
|
3743
|
-
readonly findings: readonly DoctorFinding[];
|
|
3744
|
-
readonly ok: boolean;
|
|
3745
|
-
}
|
|
3746
|
-
/** One identity's raw `identity.json`, unparsed — `runDoctor` does its own JSON.parse/schema validation so one malformed file never aborts the rest of the report. */
|
|
3747
|
-
interface DoctorIdentityInput {
|
|
3748
|
-
readonly name: string;
|
|
3749
|
-
readonly path: string;
|
|
3750
|
-
readonly raw: string | undefined;
|
|
3751
|
-
/** The identity's own farm root (`identitiesDir/<name>`) — the account name the Keychain lookup uses. */
|
|
3752
|
-
readonly farmRoot: string;
|
|
3753
|
-
}
|
|
3754
|
-
/** One configuration profile's raw `<name>.json`, unparsed. */
|
|
3755
|
-
interface DoctorConfigProfileInput {
|
|
3756
|
-
readonly name: string;
|
|
3757
|
-
readonly path: string;
|
|
3758
|
-
readonly raw: string | undefined;
|
|
3759
|
-
}
|
|
3760
|
-
/** One provider's raw `<name>.json`, unparsed. */
|
|
3761
|
-
interface DoctorProviderInput {
|
|
3762
|
-
readonly name: string;
|
|
3763
|
-
readonly path: string;
|
|
3764
|
-
readonly raw: string | undefined;
|
|
5356
|
+
/** Raised by `removeDirectoryRule`, `updateDirectoryRule` and `rule show` when no rule matches the given path exactly. */
|
|
5357
|
+
declare class DirectoryRuleNotFoundError extends CliError {
|
|
5358
|
+
readonly rulePath: string;
|
|
5359
|
+
constructor(rulePath: string);
|
|
3765
5360
|
}
|
|
3766
|
-
/**
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
readonly raw: string | undefined;
|
|
5361
|
+
/** Raised by `addDirectoryRule` when neither `--config-profile` nor `--identity` is given, and by `updateDirectoryRule` when an update would leave a rule that sets nothing at all: a rule that pins and overrides nothing would do nothing. */
|
|
5362
|
+
declare class DirectoryRuleMissingTargetError extends CliError {
|
|
5363
|
+
constructor();
|
|
3770
5364
|
}
|
|
3771
|
-
/**
|
|
3772
|
-
|
|
3773
|
-
readonly
|
|
3774
|
-
|
|
3775
|
-
} | {
|
|
3776
|
-
readonly ok: false;
|
|
3777
|
-
readonly message: string;
|
|
3778
|
-
};
|
|
3779
|
-
/**
|
|
3780
|
-
* Where a bare command name resolves for the two names this tool owns.
|
|
3781
|
-
*
|
|
3782
|
-
* `ownExecutablePath` is this process's own PATH-visible location (`realOwnExecutablePath()`); `agentShim` is `findPathShadow`'s verdict for a bare `agent-shim` against the directory that executable lives in. `claude` is only populated when a shim is actually enabled — without one, a `claude` on PATH is Claude Code's own binary, which is not a shadow of anything.
|
|
3783
|
-
*/
|
|
3784
|
-
interface DoctorPathResolution {
|
|
3785
|
-
readonly ownExecutablePath: string;
|
|
3786
|
-
readonly agentShim: PathShadowStatus;
|
|
3787
|
-
readonly claude?: PathShadowStatus;
|
|
5365
|
+
/** Raised by `addDirectoryRule` when a rule for the exact path already exists: `rule add` creates, `rule set` updates. */
|
|
5366
|
+
declare class DirectoryRuleAlreadyExistsError extends CliError {
|
|
5367
|
+
readonly rulePath: string;
|
|
5368
|
+
constructor(rulePath: string);
|
|
3788
5369
|
}
|
|
3789
|
-
/**
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
readonly
|
|
3798
|
-
readonly
|
|
3799
|
-
readonly directoryRules: DoctorFileInput;
|
|
3800
|
-
readonly globalConfig: DoctorFileInput;
|
|
3801
|
-
readonly categoriesLocal: DoctorFileInput;
|
|
3802
|
-
readonly activeIdentity: DoctorFileInput;
|
|
3803
|
-
readonly binaryDiscovery: DoctorBinaryDiscovery;
|
|
3804
|
-
/** Whether `agent-shim shim enable` has been run, and whether its recorded target still exists on disk — pre-resolved by the wiring layer, since checking a file's existence is real I/O, not a parse-shaped pure operation. */
|
|
3805
|
-
readonly claudeShim: {
|
|
3806
|
-
readonly state: ClaudeShimState | undefined;
|
|
3807
|
-
readonly targetExists: boolean;
|
|
3808
|
-
};
|
|
3809
|
-
/** Which executables a bare `agent-shim` (and, when the shim is enabled, a bare `claude`) would actually run — pre-resolved by the wiring layer, since scanning PATH is real I/O. */
|
|
3810
|
-
readonly pathResolution: DoctorPathResolution;
|
|
3811
|
-
/** The resolved state root (`paths.root`), whose directory name says whether this installation still lives under the former `.claude-use` name. */
|
|
3812
|
-
readonly rootPath: string;
|
|
3813
|
-
/** Runs `security find-generic-password` for the per-identity Keychain check. Omit to skip that check entirely (e.g. off macOS). */
|
|
3814
|
-
readonly run?: RunPort;
|
|
3815
|
-
/** `process.platform` in real use; the Keychain check only ever runs when this is `"darwin"`. */
|
|
3816
|
-
readonly platform: string;
|
|
3817
|
-
/** The headroom daemon's state.json plus a zombie-aware liveness predicate for the pids it names (a defunct daemon serves nothing but still answers signal 0). Omit the raw text when the daemon has never run; that is a pass, not a failure. */
|
|
3818
|
-
readonly headroom: {
|
|
3819
|
-
readonly state: DoctorFileInput;
|
|
3820
|
-
readonly isRunning: (pid: number) => boolean;
|
|
3821
|
-
};
|
|
5370
|
+
/** Reads `~/.agent-shim/directory-rules.json`, or an empty rule set when the file does not exist yet. */
|
|
5371
|
+
declare function readDirectoryRules(paths: LayoutPaths): DirectoryRules;
|
|
5372
|
+
/** Validates and writes the whole `~/.agent-shim/directory-rules.json` file. Exported so `src/configure.ts` can update a single rule's `categories`/`entries` in place without duplicating this validate-then-write step. Throws `ConfigValidationError` when `rules` fails `DirectoryRulesSchema`, rather than letting the underlying `ZodError` escape as an unhandled crash. */
|
|
5373
|
+
declare function writeDirectoryRules(paths: LayoutPaths, rules: DirectoryRules): void;
|
|
5374
|
+
/** Lists every directory rule, in file order. */
|
|
5375
|
+
declare function listDirectoryRules(paths: LayoutPaths): readonly DirectoryRule[];
|
|
5376
|
+
/** Inputs to `addDirectoryRule` beyond the path itself. */
|
|
5377
|
+
interface AddDirectoryRuleOptions {
|
|
5378
|
+
readonly configProfile?: string;
|
|
5379
|
+
readonly identity?: string;
|
|
3822
5380
|
}
|
|
3823
5381
|
/**
|
|
3824
|
-
*
|
|
3825
|
-
*
|
|
3826
|
-
* Deliberately identity/directory-agnostic, unlike `runCheck` — there is no single cascade to resolve `doctor` against, so it never touches settings-exposure (which only means anything relative to one resolved cascade).
|
|
3827
|
-
*
|
|
3828
|
-
* Every check aggregates rather than throws: a malformed file becomes one `fail` finding for that file, not an aborted report. This is the one place in the codebase that deliberately breaks the "throw a validation error and let it propagate" convention every other command relies on — `doctor`'s whole purpose is to survive a broken file and keep auditing everything else.
|
|
5382
|
+
* Adds a new directory rule for `rulePath`. Throws `DirectoryRuleAlreadyExistsError` when a rule for that exact path already exists (`updateDirectoryRule` changes one), and `DirectoryRuleMissingTargetError` when neither `configProfile` nor `identity` is given, since a rule that pins neither would do nothing.
|
|
3829
5383
|
*/
|
|
3830
|
-
declare function
|
|
3831
|
-
/**
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
readonly paths: LayoutPaths;
|
|
3836
|
-
readonly env: NodeJS.ProcessEnv;
|
|
5384
|
+
declare function addDirectoryRule(paths: LayoutPaths, rulePath: string, options: AddDirectoryRuleOptions): DirectoryRule;
|
|
5385
|
+
/** The fields `updateDirectoryRule` changes. A value of `false` removes that field from the rule. */
|
|
5386
|
+
interface UpdateDirectoryRuleOptions {
|
|
5387
|
+
readonly configProfile?: string | false;
|
|
5388
|
+
readonly identity?: string | false;
|
|
3837
5389
|
}
|
|
3838
5390
|
/**
|
|
3839
|
-
*
|
|
5391
|
+
* Updates the existing directory rule for `rulePath` in place, keeping its position in the file and every field not named. Throws `DirectoryRuleNotFoundError` when no rule matches that exact path, and `DirectoryRuleMissingTargetError` when the update would leave a rule that does nothing (remove it with `removeDirectoryRule` instead).
|
|
3840
5392
|
*/
|
|
3841
|
-
declare function
|
|
5393
|
+
declare function updateDirectoryRule(paths: LayoutPaths, rulePath: string, options: UpdateDirectoryRuleOptions): DirectoryRule;
|
|
5394
|
+
/** Removes the directory rule for `rulePath`. Throws `DirectoryRuleNotFoundError` when no rule matches that exact path. */
|
|
5395
|
+
declare function removeDirectoryRule(paths: LayoutPaths, rulePath: string): void;
|
|
3842
5396
|
|
|
3843
5397
|
/** What a launch's one-off command-line/environment overrides resolve to: the `cliOverride` layer `src/resolve/walk.ts`'s `assembleCascade` composes last, so it beats every other layer. */
|
|
3844
5398
|
interface CliOverride {
|
|
@@ -3986,5 +5540,5 @@ interface PrepareClaudeLaunchOptions {
|
|
|
3986
5540
|
*/
|
|
3987
5541
|
declare function prepareClaudeLaunch(options: PrepareClaudeLaunchOptions): LaunchPlan;
|
|
3988
5542
|
|
|
3989
|
-
export { AMBIENT_CREDENTIAL_VARS, CONNECT_INTERCEPT_HOST, CONNECT_INTERCEPT_HOSTS, CONNECT_LIMITS, CONTROL_PATH_PREFIX, CategoryClassificationOverlaySchema, CategoryClassificationSchema, CategoryMapSchema, CliError, ConfigProfileSchema, CredentialCacheSchema, CredentialSchema, CredentialSourceSchema, DirectoryRuleAlreadyExistsError, DirectoryRuleMissingTargetError, DirectoryRuleNotFoundError, DirectoryRuleSchema, DirectoryRulesSchema, EXIT_FAILURE, EXIT_USAGE, EntryValueSchema, FARM_MANIFEST_FILENAME, FrontDoorStartError, GlobalConfigSchema, HeadroomStartError, IdentityAlreadyExistsError, IdentityNotFoundError, IdentitySchema, InvalidCategoryNameError, InvalidIdentityNameError, InvalidProviderNameError, LaunchRefusedError, LegacyProviderFileError, PROMPT_CACHE_TTL_MS, PlanClassSchema, PoolNameSchema, PoolNotFoundError, PoolPickReportSchema, PoolSchema, PortableConfigSchema, ProfileAlreadyExistsError, ProfileNotFoundError, ProviderAlreadyExistsError, ProviderKindMismatchError, ProviderNotFoundError, ProviderSchema, RC_IDLE_EXPIRY_MS, RC_ORPC_PATH_PREFIX, RC_PENDING_DEADLINE_MS, RC_PERMISSION_MODES, RC_REQUEST_PARSE_CAP_BYTES, RC_SELF_HOST_ENV, RC_SELF_HOST_KEEPALIVE_MS, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE, RC_SELF_HOST_RETENTION_MS, RC_SELF_HOST_SCOPE_LIST, RC_SELF_HOST_WORKER_JWT_TTL_SECONDS, RC_SESSIONS_PATH_PREFIX, RC_STREAM_BACKOFF_MS, ROUTED_PATH_PREFIX, RcPermissionModeSchema, RcStreamEnvelopeSchema, RcStreamEventSchema, UsageError, UsageSnapshotError, UsageSnapshotSchema, WhenSchema, addDirectoryRule, addIdentity, addPool, addProvider, answerRcControlRequest, buildEntryFacts, buildLayoutPaths, buildRcControlResponsePayload, buildRcEventWriteBody, buildRcInterruptPayload, buildRcSetModelPayload, buildRcSetPermissionModePayload, buildRcUserMessagePayload, carryOver, checkReportHasWarnings, checkReportToJson, collectCheckReport, collectDoctorReport, collectPoolPick, createLeafCache, createProfile, createRcApiNodeHandler, createRcApiRouter, createRcControlHandler, createRcCredentialStore, createRcEventFanout, createRcSelfHostSurface, createRcSessionTracker, createRcStreamHub, createSseParser, describeProviderEndpoint, detectAmbientCredential, effectiveWindow, ensureCa, ensureFrontDoor, ensureHeadroom, evaluateAmbientCredentialGuard, evaluateWhen, formatAmbientCredentialGuardMessage, formatCheckReport, formatDoctorReport, forwardableHeaders, frontDoorRcApiClient, frontDoorRcControl, generateCa, identityExists, injectRcUserMessage, interruptRcSession, isIdentityDirectoryName, isInterceptedHost, isRcPermissionMode, lateRcEventDial, lateRcStreamDial, listDirectoryRules, listIdentities, listProfiles, listProviders, listUsageSnapshots, matchBranch, mintLeaf, mintRcSelfHostCredential, observingRoutedRoute, parseConnectTarget, parseRcStreamEnvelope, planOf, prepareClaudeLaunch, prepareLaunch, profileExists, providerExists, rankPool, rcEventWriteResultFromAnswer, rcObserverAsPassthrough, rcSelfHostFromEnv, readActiveIdentity, readDirectoryRules, readFarmManifest, readGlobalConfig, readIdentity, readPools, readProfile, readProvider, readRcSelfHostRecord, readUsageSnapshot, realConnectCertStore, realConnectEffects, realRcControlTransport, realRcEventDial, realRcStreamDial, recoverFarm, recoveryDiagnostics, removeDirectoryRule, removeIdentity, removePool, removeProfile, removeProvider, requirePool, resolveAgentShimHome, resolveClaudeHome, resolveDecisions, resolveLayoutPaths, resolveSupervisorConfig, resyncFarm, runCheck, runDoctor, runFrontDoorSupervisor, runLauncher, runSupervisor, servedByPipeline, setAllowAmbientCredential, setDefaultConfigProfile, setGlobalDefaultProfile, setIdentityCredential, setPool, setProfileCategories, setProfileEntries, setProfileLaunchFlags, setProfileMetadata, setRcSessionModel, setRcSessionPermissionMode, snapshotPath, spawnClaude, startConnectServer, topLevelNames, updateDirectoryRule, updateProvider, useIdentity, writeDirectoryRules };
|
|
3990
|
-
export type { AddDirectoryRuleOptions, AddProviderInput, AmbientCredentialDetection, AmbientCredentialGuardResult, AmbientCredentialVar, BuildEntryFactsParams, CaMaterial, Candidate, CarryOverParams, CarryOverResult, CategoryMap, CheckReport, CollectCheckReportParams, CollectDoctorReportParams, CompiledRule, ConditionContext, ConfigProfile, ConnectCertStore, ConnectEffects, ConnectLimits, ConnectLocalSurface, ConnectServerConfig, ConnectServerHandle, ConnectTarget, Credential, CredentialSource, Decision, Diagnostic, DirectoryRule, DirectoryRules, DoctorReport, EffectiveWindow, EliminatedRule, EnsureFrontDoorPorts, EnsureHeadroomPorts, EntryFact, EntryFacts, EntryValue, EvaluateAmbientCredentialGuardParams, FlattenedCascade, FrontDoorRcControl, FrontDoorSupervisorPorts, GlobalConfig, HeadroomSupervisorConfig, Identity, IdentityCredentialChange, IdentityListEntry, IdentityListing, InjectedCredential, LaunchPlan, Layer, LayerId, LayoutPaths, LeafCert, PlanClass, Pool, PoolMember, PoolPickReport, PoolRanking, PortableConfig, PrepareClaudeLaunchOptions, PrepareLaunchParams, ProfileListEntry, Provider, ProviderListEntry, RankPoolInput, RcAnswerDecision, RcAnswerDeps, RcApiClient, RcApiDeps, RcApiRouter, RcControlAnswer, RcControlHandlerDeps, RcControlRequestDeps, RcControlTransport, RcCredentialStore, RcDialAnswer, RcDialTarget, RcEventDial, RcEventFanout, RcEventWriteResult, RcExchangeObserver, RcInjectDeps, RcObservedCredential, RcObservedRequest, RcPendingRequestSummary, RcPermissionMode, RcPresenceAnswer, RcSelfHostCredentialRecord, RcSelfHostDeps, RcSelfHostMintResult, RcSelfHostSurface, RcSessionStatus, RcSessionSummary, RcSessionTracker, RcSessionTrackerDeps, RcStreamAnswer, RcStreamDial, RcStreamEnvelope, RcStreamEvent, RcStreamHub, RcStreamHubDeps, RcWorkerFact, RcWriteHeaders, RecoverFarmParams, RecoveryResult, ResolveDecisionsInput, ResolvedState, ResyncFarmParams, ResyncFarmResult, RunCheckParams, RunDoctorParams, RunFrontDoorSupervisorOptions, RunLauncherParams, RunSupervisorOptions, SpawnClaudeParams, SseParsedEvent, StickyPick, SupervisorPorts, UnreadableIdentityListEntry, UpdateDirectoryRuleOptions, UpdateProviderInput, UsageReadFs, UsageSnapshot, WhenCondition, WhenEvaluation };
|
|
5543
|
+
export { AMBIENT_CREDENTIAL_VARS, CHECK_CREDENTIAL_APPLIES, CONNECT_INTERCEPT_HOST, CONNECT_INTERCEPT_HOSTS, CONNECT_LIMITS, CONTROL_PATH_PREFIX, CategoryClassificationOverlaySchema, CategoryClassificationSchema, CategoryMapSchema, CheckReportJsonSchema, CheckRunInputSchema, CliError, ConfigProfileSchema, CredentialCacheSchema, CredentialSchema, CredentialSourceSchema, DirectoryRuleAlreadyExistsError, DirectoryRuleMissingTargetError, DirectoryRuleNotFoundError, DirectoryRuleSchema, DirectoryRulesSchema, DoctorFindingSchema, DoctorRunOutputSchema, EXIT_FAILURE, EXIT_USAGE, EffectiveWindowSchema, EntryValueSchema, FARM_MANIFEST_FILENAME, FrontDoorSessionStatusSchema, FrontDoorSessionsOutputSchema, FrontDoorStartError, FrontDoorStateSchema, FrontDoorStatusOutputSchema, GlobalConfigSchema, HeadroomSocketTargetSchema, HeadroomStartError, IdentityAlreadyExistsError, IdentityNotFoundError, IdentitySchema, InvalidCategoryNameError, InvalidIdentityNameError, InvalidProviderNameError, LaunchRefusedError, LegacyProviderFileError, PROMPT_CACHE_TTL_MS, PlanClassSchema, PoolNameSchema, PoolNotFoundError, PoolPickReportSchema, PoolSchema, PortableConfigSchema, ProfileAlreadyExistsError, ProfileNotFoundError, ProviderAlreadyExistsError, ProviderKindMismatchError, ProviderNotFoundError, ProviderSchema, RC_IDLE_EXPIRY_MS, RC_ORPC_PATH_PREFIX, RC_PENDING_DEADLINE_MS, RC_PERMISSION_MODES, RC_REQUEST_PARSE_CAP_BYTES, RC_SELF_HOST_ENV, RC_SELF_HOST_KEEPALIVE_MS, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE, RC_SELF_HOST_RETENTION_MS, RC_SELF_HOST_SCOPE_LIST, RC_SELF_HOST_WORKER_JWT_TTL_SECONDS, RC_SESSIONS_PATH_PREFIX, RC_STREAM_BACKOFF_MS, ROUTED_PATH_PREFIX, RcPermissionModeSchema, RcStreamEnvelopeSchema, RcStreamEventSchema, UsageError, UsageListOutputSchema, UsageSnapshotError, UsageSnapshotSchema, UsageWindowsInputSchema, UsageWindowsOutputSchema, WhenSchema, addDirectoryRule, addIdentity, addPool, addProvider, answerRcControlRequest, buildEntryFacts, buildLayoutPaths, buildRcControlResponsePayload, buildRcEventWriteBody, buildRcInterruptPayload, buildRcSetModelPayload, buildRcSetPermissionModePayload, buildRcUserMessagePayload, carryOver, checkReportHasWarnings, checkReportToJson, collectCheckReport, collectDoctorReport, collectFrontDoorStatus, collectPoolPick, createControlApiRouter, createDoorApiNodeHandler, createDoorApiRouter, createLeafCache, createProfile, createRcApiNodeHandler, createRcApiRouter, createRcControlHandler, createRcCredentialStore, createRcEventFanout, createRcSelfHostSurface, createRcSessionTracker, createRcStreamHub, createSseParser, describeProviderEndpoint, detectAmbientCredential, doorApiAuth, doorApiNodeHandlerOf, effectiveWindow, ensureCa, ensureFrontDoor, ensureHeadroom, evaluateAmbientCredentialGuard, evaluateWhen, formatAmbientCredentialGuardMessage, formatCheckReport, formatDoctorReport, formatFrontDoorStatus, forwardableHeaders, frontDoorApiClient, frontDoorApiLink, frontDoorRcApiClient, frontDoorRcControl, generateCa, headroomSocketTarget, identityExists, injectRcUserMessage, interruptRcSession, isIdentityDirectoryName, isInterceptedHost, isRcPermissionMode, lateRcEventDial, lateRcStreamDial, listDirectoryRules, listIdentities, listProfiles, listProviders, listUsageSnapshots, matchBranch, mintLeaf, mintRcSelfHostCredential, observingRoutedRoute, parseConnectTarget, parseRcStreamEnvelope, planOf, prepareClaudeLaunch, prepareLaunch, profileExists, providerExists, rankPool, rcEventWriteResultFromAnswer, rcObserverAsPassthrough, rcSelfHostFromEnv, readActiveIdentity, readDirectoryRules, readFarmManifest, readGlobalConfig, readIdentity, readPools, readProfile, readProvider, readRcSelfHostRecord, readUsageSnapshot, realConnectCertStore, realConnectEffects, realRcControlTransport, realRcEventDial, realRcStreamDial, recoverFarm, recoveryDiagnostics, removeDirectoryRule, removeIdentity, removePool, removeProfile, removeProvider, requirePool, resolveAgentShimHome, resolveClaudeHome, resolveDecisions, resolveLayoutPaths, resolveSupervisorConfig, resyncFarm, runCheck, runDoctor, runFrontDoorSupervisor, runLauncher, runSupervisor, servedByPipeline, setAllowAmbientCredential, setDefaultConfigProfile, setGlobalDefaultProfile, setIdentityCredential, setPool, setProfileCategories, setProfileEntries, setProfileLaunchFlags, setProfileMetadata, setRcSessionModel, setRcSessionPermissionMode, snapshotPath, spawnClaude, startConnectServer, topLevelNames, updateDirectoryRule, updateProvider, useIdentity, writeDirectoryRules };
|
|
5544
|
+
export type { AddDirectoryRuleOptions, AddProviderInput, AmbientCredentialDetection, AmbientCredentialGuardResult, AmbientCredentialVar, BuildEntryFactsParams, CaMaterial, Candidate, CarryOverParams, CarryOverResult, CategoryMap, CheckReport, CheckReportJson, CollectCheckReportParams, CollectDoctorReportParams, CompiledRule, ConditionContext, ConfigProfile, ConnectCertStore, ConnectEffects, ConnectLimits, ConnectLocalSurface, ConnectServerConfig, ConnectServerHandle, ConnectTarget, ControlApiClient, ControlApiDeps, ControlApiRouter, Credential, CredentialSource, Decision, Diagnostic, DirectoryRule, DirectoryRules, DoctorReport, DoorApiClient, DoorApiContext, DoorApiDeps, DoorApiRouter, EffectiveWindow, EliminatedRule, EnsureFrontDoorPorts, EnsureHeadroomPorts, EntryFact, EntryFacts, EntryValue, EvaluateAmbientCredentialGuardParams, FlattenedCascade, FrontDoorRcControl, FrontDoorSessionStatus, FrontDoorStatus, FrontDoorSupervisorPorts, GlobalConfig, HeadroomSupervisorConfig, Identity, IdentityCredentialChange, IdentityListEntry, IdentityListing, InjectedCredential, LaunchPlan, Layer, LayerId, LayoutPaths, LeafCert, PlanClass, Pool, PoolMember, PoolPickReport, PoolRanking, PortableConfig, PrepareClaudeLaunchOptions, PrepareLaunchParams, ProfileListEntry, Provider, ProviderListEntry, RankPoolInput, RcAnswerDecision, RcAnswerDeps, RcApiClient, RcApiDeps, RcApiRouter, RcControlAnswer, RcControlHandlerDeps, RcControlRequestDeps, RcControlTransport, RcCredentialStore, RcDialAnswer, RcDialTarget, RcEventDial, RcEventFanout, RcEventWriteResult, RcExchangeObserver, RcInjectDeps, RcObservedCredential, RcObservedRequest, RcPendingRequestSummary, RcPermissionMode, RcPresenceAnswer, RcSelfHostCredentialRecord, RcSelfHostDeps, RcSelfHostMintResult, RcSelfHostSurface, RcSessionStatus, RcSessionSummary, RcSessionTracker, RcSessionTrackerDeps, RcStreamAnswer, RcStreamDial, RcStreamEnvelope, RcStreamEvent, RcStreamHub, RcStreamHubDeps, RcWorkerFact, RcWriteHeaders, RecoverFarmParams, RecoveryResult, ResolveDecisionsInput, ResolvedState, ResyncFarmParams, ResyncFarmResult, RunCheckParams, RunDoctorParams, RunFrontDoorSupervisorOptions, RunLauncherParams, RunSupervisorOptions, SpawnClaudeParams, SseParsedEvent, StickyPick, SupervisorPorts, UnreadableIdentityListEntry, UpdateDirectoryRuleOptions, UpdateProviderInput, UsageReadFs, UsageSnapshot, WhenCondition, WhenEvaluation };
|