@fastagent-sh/fastagent 0.22.1 → 0.23.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.
Files changed (103) hide show
  1. package/dist/channels/agentcore-protocol.d.ts +2 -1
  2. package/dist/channels/agentcore-service.js +10 -18
  3. package/dist/channels/agentcore.js +6 -3
  4. package/dist/channels/control.js +23 -0
  5. package/dist/channels/slack/config-api.d.ts +2 -2
  6. package/dist/channels/slack/config-api.js +2 -2
  7. package/dist/channels/slack/onboard.js +2 -2
  8. package/dist/channels/slack/register-webhook.js +2 -2
  9. package/dist/channels/slack/slack-api.js +4 -4
  10. package/dist/cli/add-feishu.js +4 -2
  11. package/dist/cli/auth-view.d.ts +15 -6
  12. package/dist/cli/auth-view.js +24 -8
  13. package/dist/cli/box-login.d.ts +33 -0
  14. package/dist/cli/box-login.js +162 -0
  15. package/dist/cli/commands/deploy/agentcore.js +48 -11
  16. package/dist/cli/commands/deploy/docker.js +24 -13
  17. package/dist/cli/commands/deploy/fly.js +30 -7
  18. package/dist/cli/commands/deploy/railway.js +21 -7
  19. package/dist/cli/commands/deploy/shared.d.ts +18 -17
  20. package/dist/cli/commands/deploy/shared.js +20 -21
  21. package/dist/cli/commands/destroy.js +2 -2
  22. package/dist/cli/commands/info.js +9 -6
  23. package/dist/cli/commands/invoke.js +2 -2
  24. package/dist/cli/commands/login.d.ts +7 -1
  25. package/dist/cli/commands/login.js +123 -10
  26. package/dist/cli/commands/logs.js +2 -2
  27. package/dist/cli/commands/models.d.ts +4 -1
  28. package/dist/cli/commands/models.js +37 -4
  29. package/dist/cli/commands/routine-run.js +2 -2
  30. package/dist/cli/commands/start.d.ts +0 -5
  31. package/dist/cli/commands/start.js +3 -13
  32. package/dist/cli/kernel.d.ts +2 -0
  33. package/dist/cli/kernel.js +1 -1
  34. package/dist/cli/login-relay.d.ts +38 -0
  35. package/dist/cli/login-relay.js +121 -0
  36. package/dist/cli/program.js +46 -8
  37. package/dist/cli/shared.d.ts +4 -4
  38. package/dist/cli/shared.js +24 -30
  39. package/dist/deploy/agentcore/plan.d.ts +10 -11
  40. package/dist/deploy/agentcore/plan.js +8 -14
  41. package/dist/deploy/agentcore/run.d.ts +8 -1
  42. package/dist/deploy/agentcore/run.js +20 -14
  43. package/dist/deploy/agentcore/shell.d.ts +25 -0
  44. package/dist/deploy/agentcore/shell.js +202 -0
  45. package/dist/deploy/box-shell.d.ts +43 -0
  46. package/dist/deploy/box-shell.js +28 -0
  47. package/dist/deploy/build-context.js +16 -7
  48. package/dist/deploy/channel-ingress.d.ts +20 -1
  49. package/dist/deploy/channel-ingress.js +34 -7
  50. package/dist/deploy/container.d.ts +14 -0
  51. package/dist/deploy/container.js +45 -1
  52. package/dist/deploy/docker/plan.d.ts +7 -3
  53. package/dist/deploy/docker/plan.js +9 -14
  54. package/dist/deploy/docker/run.d.ts +14 -7
  55. package/dist/deploy/docker/run.js +58 -35
  56. package/dist/deploy/fly/plan.d.ts +6 -3
  57. package/dist/deploy/fly/plan.js +6 -8
  58. package/dist/deploy/fly/run.d.ts +8 -2
  59. package/dist/deploy/fly/run.js +15 -25
  60. package/dist/deploy/preflight.d.ts +9 -7
  61. package/dist/deploy/preflight.js +74 -20
  62. package/dist/deploy/railway/plan.d.ts +6 -3
  63. package/dist/deploy/railway/plan.js +7 -9
  64. package/dist/deploy/railway/run.d.ts +10 -6
  65. package/dist/deploy/railway/run.js +29 -13
  66. package/dist/deploy/runner.d.ts +16 -0
  67. package/dist/deploy/runner.js +31 -0
  68. package/dist/deploy/secrets.d.ts +4 -13
  69. package/dist/deploy/secrets.js +8 -27
  70. package/dist/dev-supervisor.js +5 -2
  71. package/dist/engines/pi/agent-models.d.ts +70 -0
  72. package/dist/engines/pi/agent-models.js +93 -0
  73. package/dist/engines/pi/auth.d.ts +56 -3
  74. package/dist/engines/pi/auth.js +63 -16
  75. package/dist/engines/pi/config.d.ts +0 -25
  76. package/dist/engines/pi/config.js +3 -37
  77. package/dist/engines/pi/create.d.ts +22 -16
  78. package/dist/engines/pi/create.js +28 -28
  79. package/dist/engines/pi/entry-images.d.ts +14 -0
  80. package/dist/engines/pi/entry-images.js +23 -0
  81. package/dist/engines/pi/invoke-session.js +6 -4
  82. package/dist/engines/pi/login.d.ts +20 -13
  83. package/dist/engines/pi/login.js +19 -12
  84. package/dist/engines/pi/models.d.ts +115 -36
  85. package/dist/engines/pi/models.js +218 -48
  86. package/dist/engines/pi/open.d.ts +42 -11
  87. package/dist/engines/pi/open.js +53 -21
  88. package/dist/engines/pi/service.d.ts +2 -2
  89. package/dist/engines/pi/service.js +1 -0
  90. package/dist/engines/pi/session-builder.d.ts +3 -2
  91. package/dist/engines/pi/session-builder.js +28 -58
  92. package/dist/engines/pi/session-control.js +14 -3
  93. package/dist/engines/pi/turn-kit.js +11 -5
  94. package/dist/open-url.d.ts +15 -1
  95. package/dist/open-url.js +35 -3
  96. package/dist/paths.d.ts +4 -2
  97. package/dist/paths.js +6 -2
  98. package/dist/pi.d.ts +5 -3
  99. package/dist/pi.js +3 -2
  100. package/dist/service.d.ts +5 -8
  101. package/dist/session-remote.js +21 -0
  102. package/dist/session.d.ts +28 -7
  103. package/package.json +2 -1
@@ -4,6 +4,7 @@ import * as Effect from "effect/Effect";
4
4
  import * as Fiber from "effect/Fiber";
5
5
  import * as Queue from "effect/Queue";
6
6
  import { ABORTED_CODE, SESSION_BUSY_CODE, } from "../../agent.js";
7
+ import { entryImages } from "./entry-images.js";
7
8
  import { cancellableStream } from "../../collect.js";
8
9
  import { log } from "../../log.js";
9
10
  import { toRetryScheduledEvent } from "./retry-event.js";
@@ -105,9 +106,10 @@ function reportUserMessages(session, report) {
105
106
  return Effect.acquireRelease(Effect.sync(() => {
106
107
  record.appendMessage = (message) => {
107
108
  const entryId = append.call(record, message);
108
- // The same text `entries()` publishes for this entry (session-control.ts toSessionEntry).
109
- if (message.role === "user")
110
- report(entryId, contentText(message.content, ""));
109
+ // The same text and images `entries()` publishes for this entry (session-control.ts toSessionEntry).
110
+ if (message.role === "user") {
111
+ report({ entryId, text: contentText(message.content, ""), ...entryImages(entryId, message) });
112
+ }
111
113
  return entryId;
112
114
  };
113
115
  }), () => Effect.sync(() => {
@@ -240,7 +242,7 @@ export function createPiAgentFromSession(options) {
240
242
  if (OWED_BY_THE_RUN.has(error.event))
241
243
  extensionFailure ??= `${error.event} failed (${error.extensionPath}): ${error.error}`;
242
244
  })), (unsubscribe) => Effect.sync(unsubscribe));
243
- yield* reportUserMessages(session, (entryId, text) => observe({ type: "user_message", timestamp: Date.now(), runId, data: { entryId, text } }));
245
+ yield* reportUserMessages(session, (data) => observe({ type: "user_message", timestamp: Date.now(), runId, data }));
244
246
  const extensionTurns = trackExtensionTurns(session);
245
247
  // Completing the gate can run waiting controls synchronously; their queue events must be observed.
246
248
  yield* Deferred.succeed(bound, session);
@@ -4,7 +4,7 @@
4
4
  * (one writer, one lock/corruption semantics); {@link loginOptions} is the list a picker offers. `fastagent login` is
5
5
  * one front end ({@link loginFlow}: terminal menus, then {@link login}); a GUI client is another.
6
6
  */
7
- import { type AuthInteraction, type Provider } from "@earendil-works/pi-ai";
7
+ import { type AuthInteraction, type CredentialStore, type Provider } from "@earendil-works/pi-ai";
8
8
  export type LoginMethod = "oauth" | "api_key";
9
9
  /** The user backed out of a prompt/menu, or the flow was aborted — a decision, not a failure. */
10
10
  export declare class LoginCancelled extends Error {
@@ -18,26 +18,32 @@ export interface LoginOption {
18
18
  /** An OAuth login backed by a provider subscription. */
19
19
  subscription: boolean;
20
20
  /**
21
- * What the file holds for this provider now. It keeps ONE credential per provider, so signing in with the other
21
+ * What the store holds for this provider now. It keeps ONE credential per provider, so signing in with the other
22
22
  * method replaces it — worth a warning in a client.
23
23
  */
24
24
  stored?: LoginMethod;
25
25
  }
26
26
  /**
27
- * Every interactive sign-in of pi's built-in providers, with what `authPath` already holds for each. A provider whose
28
- * key can only come from its env var offers none and is left out.
27
+ * Every interactive sign-in of pi's built-in providers, with what `credentials` (a credentials file, or the caller's
28
+ * own store) already holds for each. A provider whose key can only come from its env var offers none and is left out.
29
29
  */
30
- export declare function loginOptions(authPath: string): Promise<LoginOption[]>;
30
+ export declare function loginOptions(credentials: string | CredentialStore): Promise<LoginOption[]>;
31
31
  /** {@link loginOptions} over pi's built-ins plus `providers` (a same id replaces one). Not public: a test seam. */
32
- export declare function loginOptionsOver(authPath: string, providers?: readonly Provider[]): Promise<LoginOption[]>;
33
- export interface LoginRequest {
32
+ export declare function loginOptionsOver(credentials: string | CredentialStore, providers?: readonly Provider[]): Promise<LoginOption[]>;
33
+ export type LoginRequest = {
34
34
  provider: string;
35
35
  method: LoginMethod;
36
- /** The credentials file the sign-in is written to. */
37
- authPath: string;
38
36
  /** pi-ai's own interaction: prompts (`text`, `secret`, `select`, `manual_code`) and events (`auth_url`, …). */
39
37
  interaction: AuthInteraction;
40
- }
38
+ } & ({
39
+ /** The credentials file the sign-in is written to. */
40
+ authPath: string;
41
+ credentialStore?: never;
42
+ } | {
43
+ /** The caller's own store the sign-in is written to, in place of any file. */
44
+ credentialStore: CredentialStore;
45
+ authPath?: never;
46
+ });
41
47
  export interface LoginResult {
42
48
  provider: string;
43
49
  method: LoginMethod;
@@ -45,10 +51,11 @@ export interface LoginResult {
45
51
  verified: "ok" | "unknown" | "n/a";
46
52
  }
47
53
  /**
48
- * Sign in to one of pi's built-in providers and persist the credential to `authPath`.
54
+ * Sign in to one of pi's built-in providers and persist the credential to `authPath`, or to the caller's
55
+ * `credentialStore`.
49
56
  *
50
- * The file is checked FIRST (a no-op write runs the refuse-corrupt and writability checks), so a flow never runs
51
- * toward a credential that could not be saved. An entered API key is verified with one minimal request to pi's
57
+ * The store is checked FIRST (a no-op write runs the file store's refuse-corrupt and writability checks, or whatever
58
+ * the caller's store does on a write), so a flow never runs toward a credential that could not be saved. An entered API key is verified with one minimal request to pi's
52
59
  * default model for the provider (its first model when pi names none), at pi's built-in endpoint, BEFORE it is
53
60
  * written. Credentials are provider-scoped, so any of the provider's models answers the question the check asks (does
54
61
  * the provider refuse the key, HTTP 401); a key the provider rejects is never stored, and the provider's key flow runs
@@ -7,21 +7,24 @@
7
7
  import { InMemoryCredentialStore, } from "@earendil-works/pi-ai";
8
8
  import { fastagentCredentialStore } from "./auth.js";
9
9
  import { createPiModelRuntime, interactiveAuth, loginProviders, piModelsOver, probeApiKey } from "./models.js";
10
+ import { agentModels } from "./agent-models.js";
10
11
  /** The user backed out of a prompt/menu, or the flow was aborted — a decision, not a failure. */
11
12
  export class LoginCancelled extends Error {
12
13
  }
13
14
  /**
14
- * Every interactive sign-in of pi's built-in providers, with what `authPath` already holds for each. A provider whose
15
- * key can only come from its env var offers none and is left out.
15
+ * Every interactive sign-in of pi's built-in providers, with what `credentials` (a credentials file, or the caller's
16
+ * own store) already holds for each. A provider whose key can only come from its env var offers none and is left out.
16
17
  */
17
- export function loginOptions(authPath) {
18
- return loginOptionsOver(authPath);
18
+ export function loginOptions(credentials) {
19
+ return loginOptionsOver(credentials);
19
20
  }
21
+ /** A credentials file path names fastagent's store over it; a store is used as given. */
22
+ const storeOf = (credentials) => typeof credentials === "string" ? fastagentCredentialStore(credentials) : credentials;
20
23
  /** {@link loginOptions} over pi's built-ins plus `providers` (a same id replaces one). Not public: a test seam. */
21
- export async function loginOptionsOver(authPath, providers) {
22
- // ONE read of the file: `list` is metadata only, and reading per provider would repeat a corrupt file's warning for
24
+ export async function loginOptionsOver(credentials, providers) {
25
+ // ONE read of the store: `list` is metadata only, and reading per provider would repeat a corrupt file's warning for
23
26
  // every provider.
24
- const held = new Map((await fastagentCredentialStore(authPath).list()).map((info) => [info.providerId, info.type]));
27
+ const held = new Map((await storeOf(credentials).list()).map((info) => [info.providerId, info.type]));
25
28
  const offered = [];
26
29
  for (const provider of loginProviders(providers)) {
27
30
  const methods = ["oauth", "api_key"].filter((method) => interactiveAuth(provider, method));
@@ -46,10 +49,11 @@ function anySignal(...signals) {
46
49
  return present.length === 0 ? undefined : present.length === 1 ? present[0] : AbortSignal.any(present);
47
50
  }
48
51
  /**
49
- * Sign in to one of pi's built-in providers and persist the credential to `authPath`.
52
+ * Sign in to one of pi's built-in providers and persist the credential to `authPath`, or to the caller's
53
+ * `credentialStore`.
50
54
  *
51
- * The file is checked FIRST (a no-op write runs the refuse-corrupt and writability checks), so a flow never runs
52
- * toward a credential that could not be saved. An entered API key is verified with one minimal request to pi's
55
+ * The store is checked FIRST (a no-op write runs the file store's refuse-corrupt and writability checks, or whatever
56
+ * the caller's store does on a write), so a flow never runs toward a credential that could not be saved. An entered API key is verified with one minimal request to pi's
53
57
  * default model for the provider (its first model when pi names none), at pi's built-in endpoint, BEFORE it is
54
58
  * written. Credentials are provider-scoped, so any of the provider's models answers the question the check asks (does
55
59
  * the provider refuse the key, HTTP 401); a key the provider rejects is never stored, and the provider's key flow runs
@@ -66,7 +70,10 @@ export function login(request) {
66
70
  /** {@link login}, plus {@link LoginInternals}. */
67
71
  export async function loginOver(request, internals = {}) {
68
72
  const { providers, verifyWith, agentDir } = internals;
69
- const { method, authPath, interaction } = request;
73
+ const { method, interaction } = request;
74
+ if (request.credentialStore === undefined && typeof request.authPath !== "string") {
75
+ throw new Error("login needs authPath or credentialStore: where the sign-in is written");
76
+ }
70
77
  const provider = loginProviders(providers).find((p) => p.id === request.provider);
71
78
  if (!provider)
72
79
  throw new Error(`unknown provider "${request.provider}"`);
@@ -86,7 +93,7 @@ export async function loginOver(request, internals = {}) {
86
93
  ...(providers ? { providers: [...providers] } : {}),
87
94
  })
88
95
  : piModelsOver(trial, providers);
89
- const store = fastagentCredentialStore(authPath);
96
+ const store = agentModels(undefined, request).credentials;
90
97
  await store.modify(provider.id, async () => undefined);
91
98
  const signal = interaction.signal ?? new AbortController().signal;
92
99
  const notify = (event) => interaction.notify(event);
@@ -1,17 +1,6 @@
1
1
  import type { ThinkingLevel } from "@earendil-works/pi-agent-core";
2
- import { type Api, type CredentialStore, type Model, type Models, type Provider } from "@earendil-works/pi-ai";
2
+ import { type Api, type CredentialStore, InMemoryModelsStore, type Model, type Models, type Provider } from "@earendil-works/pi-ai";
3
3
  import { ModelRuntime } from "@earendil-works/pi-coding-agent";
4
- import { type FastagentAuthOptions } from "./auth.ts";
5
- import { type AuthLayers } from "./config.ts";
6
- /** The DEFINITION-LOCAL custom-endpoint file, in pi's own models.json schema (see pi's docs/models.md). */
7
- export interface CreatePiModelsOptions extends FastagentAuthOptions {
8
- /** Credentials file (default `GLOBAL_AUTH_PATH`). A named file is an instruction: no second layer. */
9
- authPath?: string;
10
- /** Extra providers registered on top of the built-ins (same id overrides a built-in). */
11
- providers?: Provider[];
12
- }
13
- /** A `Models` with every built-in pi provider, wired to fastagent's auth. */
14
- export declare function createPiModels(options?: CreatePiModelsOptions): Models;
15
4
  /** The built-ins plus `providers` (a same id replaces a built-in), over any credential store. */
16
5
  export declare function piModelsOver(credentials: CredentialStore, providers?: readonly Provider[]): Models;
17
6
  /**
@@ -21,12 +10,6 @@ export declare function piModelsOver(credentials: CredentialStore, providers?: r
21
10
  export type AnyModel = Model<any>;
22
11
  /** The serving default for reasoning effort, pinned to what pi's TUI defaults to (its own DEFAULT_THINKING_LEVEL). */
23
12
  export declare const DEFAULT_THINKING_LEVEL: ThinkingLevel;
24
- /**
25
- * The MACHINE's custom-endpoint file, in the same schema as an agent's own: endpoints a person set up for this machine
26
- * (a local Ollama, a company gateway), which every agent here inherits the way it inherits the machine's skills.
27
- * `FASTAGENT_MODELS_PATH` moves it. It never ships: a deployed agent has only its definition's file.
28
- */
29
- export declare function machineModelsPath(env?: NodeJS.ProcessEnv): string;
30
13
  /**
31
14
  * Where an agent's custom endpoints come from, for a report: the machine file, the providers the agent inherits from
32
15
  * it, and the ones its own file overrides. Undefined when the machine has no file.
@@ -38,29 +21,110 @@ export declare function machineModels(agentDir: string): Promise<{
38
21
  } | undefined>;
39
22
  /** Whether pi ships this provider id itself, so an agent resolves it without any models.json entry. */
40
23
  export declare function isBuiltinProvider(providerId: string): boolean;
41
- /** The `ModelRuntime`-shaped sibling of {@link createPiModels}. */
42
- export declare function createPiModelRuntime(options?: FastagentAuthOptions & {
43
- /** The credentials files to read (default: the global file alone). */
44
- auth?: AuthLayers;
45
- /** The agent dir, whose {@link AGENT_MODELS_FILE} declares custom endpoints. */
24
+ export interface PiModelRuntimeOptions {
25
+ /** The store every credential is read from and refreshed into. */
26
+ credentials: CredentialStore;
27
+ /** The agent dir, whose {@link AGENT_MODELS_FILE} and {@link AGENT_MODEL_CATALOG_FILE} the registry reads. */
46
28
  agentDir?: string;
47
29
  /**
48
- * Layer the machine's models.json under the agent's (default). Off for the registry a DEPLOYED agent has, which
49
- * `deploy` must judge by: the machine's file does not ship.
30
+ * Layer the machine under the agent (default): its models.json and its model catalog ({@link globalCatalogPath}).
31
+ * Off for the registry a DEPLOYED agent has, which `deploy` must judge by: neither ships, so that registry is the
32
+ * agent's own two files over the catalog bundled with pi.
50
33
  */
51
34
  machineLayer?: boolean;
52
- /** Where the dynamic model-catalog cache goes; defaults to the agent's resolved state root. */
53
- stateRoot?: string;
54
35
  /** Extra providers for the ids the built-ins do not cover. */
55
- providers?: Provider[];
56
- /** A credential store to use instead of the files (login verifies an entered key from memory). */
36
+ providers?: readonly Provider[];
37
+ /**
38
+ * Read and write THIS catalog file instead of the layered, read-only snapshot: what a refresh runs on, since the
39
+ * refresh writes it.
40
+ */
41
+ catalogFile?: string;
42
+ /** Where a catalog refresh asks instead of pi.dev: a test seam. */
43
+ catalogBaseUrl?: string;
44
+ }
45
+ /**
46
+ * The MACHINE's model catalog: the models pi.dev lists that are newer than the catalog bundled with pi, fetched by
47
+ * `fastagent models --refresh -g`. Every agent here reads it under its own; like `~/.fastagent/models.json`, it
48
+ * never ships.
49
+ */
50
+ export declare function globalCatalogPath(): string;
51
+ /**
52
+ * Whether the machine's model catalog supplies this model, by the same rule every registry reads it with
53
+ * ({@link layeredCatalog}): an entry pi would ignore supplies nothing. The one layer a deployed agent does not have.
54
+ */
55
+ export declare function inGlobalCatalog(provider: string, id: string): Promise<boolean>;
56
+ /** The models.json a runtime for these options loads, and which model catalog it reads. */
57
+ export declare function modelRuntimeFiles(options: Omit<PiModelRuntimeOptions, "credentials">): Promise<{
58
+ models: {
59
+ path: string;
60
+ merged?: {
61
+ machine: string;
62
+ definition: string;
63
+ };
64
+ } | undefined;
65
+ create: {
66
+ modelsPath: string | null;
67
+ modelsStorePath: string;
68
+ allowModelNetwork: boolean;
69
+ catalogBaseUrl?: string | undefined;
70
+ } | {
71
+ modelsPath: string | null;
72
+ modelsStore: InMemoryModelsStore;
73
+ allowModelNetwork: boolean;
74
+ catalogBaseUrl?: string | undefined;
75
+ } | {
76
+ modelsPath: string | null;
77
+ allowModelNetwork: boolean;
78
+ catalogBaseUrl?: string | undefined;
79
+ };
80
+ }>;
81
+ /**
82
+ * This machine's registry, without an agent: pi's built-ins, the machine's models.json and its model catalog. What
83
+ * `fastagent models` lists outside an agent; {@link catalogFile} is the refresh's (it writes the file).
84
+ */
85
+ export declare function machineModelRuntime(options?: {
57
86
  credentials?: CredentialStore;
87
+ catalogFile?: string;
88
+ catalogBaseUrl?: string;
58
89
  }): Promise<ModelRuntime>;
59
- /** How a model's credential will REACH a deployed agent. */
60
- export declare function modelCredentialCarry(runtime: ModelRuntime, spec: string): {
61
- envVar?: string;
62
- inDefinition: boolean;
63
- };
90
+ /**
91
+ * Refresh the machine's catalog ({@link globalCatalogPath}) with the machine's credentials: the global credentials
92
+ * file and the environment. See {@link refreshCatalog} for what it asks and when it rejects.
93
+ */
94
+ export declare function refreshGlobalModelCatalog(options?: {
95
+ signal?: AbortSignal;
96
+ catalogBaseUrl?: string;
97
+ }): Promise<void>;
98
+ /**
99
+ * Fetch the model catalog of every provider the runtime can authenticate into its catalog file: the refresh
100
+ * `pi update --models` runs. `runtime(true)` is built over that file, `runtime(false)` over the read-only layers; the
101
+ * file-backed one is built only once the refresh is known to run, because pi's file store creates the file on read and
102
+ * a refused refresh must leave nothing behind. pi asks pi.dev only for a provider with a usable
103
+ * credential, and may refresh an expired OAuth token of the runtime's store to get one. Rejects, naming each provider
104
+ * that failed, when any part fails, when it outlasts 15 seconds, when `PI_OFFLINE` is set, and when no provider has a
105
+ * usable credential (the refresh would ask for nothing).
106
+ */
107
+ export declare function refreshCatalog(runtime: (catalogFile: boolean) => Promise<ModelRuntime>, options?: {
108
+ signal?: AbortSignal;
109
+ }): Promise<void>;
110
+ /**
111
+ * What satisfies a provider from `env` alone (its API-key variable, or an ambient source such as an AWS profile), by
112
+ * pi's own check, or undefined. Passed explicitly rather than read from `process.env`: only the environment a SHELL
113
+ * hands down is shared by every agent on the machine, and a process that has loaded an agent's `.secrets/.env` holds
114
+ * that agent's variables too. What the shell shares outranks the global credentials file (agent-models.ts),
115
+ * so a global login for such a provider is not used.
116
+ *
117
+ * `fileExists` answers for the files a source points at (an AWS profile, Google ADC): this machine's by default, which
118
+ * is right wherever the answer is about THIS machine. A deployment passes one that finds nothing, because no file of
119
+ * the builder's travels with it.
120
+ */
121
+ export declare function environmentAuthSource(providerId: string, env: NodeJS.ProcessEnv, fileExists?: (path: string) => Promise<boolean>): Promise<string | undefined>;
122
+ /**
123
+ * A registry over the given credential store. What an agent runs on is built through `agentModels`
124
+ * (agent-models.ts); this is for a registry over some OTHER store: none at all (`models`, a deploy check of what
125
+ * ships), a trial key under test (login), or the catalog file a refresh writes.
126
+ */
127
+ export declare function createPiModelRuntime(options: PiModelRuntimeOptions): Promise<ModelRuntime>;
64
128
  /**
65
129
  * EVERY provider whose `models.json` entry writes its key as a LITERAL rather than a `"$NAME"` reference or a
66
130
  * `"!cmd"`. The file ships inside the image, so a literal there is a credential in a readable layer.
@@ -76,6 +140,17 @@ export declare function modelCredentialCarry(runtime: ModelRuntime, spec: string
76
140
  * gates what IT causes; what the author wrote into their own committed file, it reports.
77
141
  */
78
142
  export declare function literalKeyProviders(agentDir: string): Promise<string[]>;
143
+ /**
144
+ * How the agent's OWN models.json supplies `providerId`'s key, read from the file for the reason
145
+ * {@link literalKeyProviders} gives: `reference` is the variable a `"$NAME"` reads (the value file must hold it),
146
+ * `inFile` a key that travels with the definition itself (a literal, or a `"!command"` run on the box), and undefined
147
+ * no apiKey there at all.
148
+ */
149
+ export declare function definitionKeyOf(agentDir: string, providerId: string): Promise<{
150
+ reference: string;
151
+ } | {
152
+ inFile: true;
153
+ } | undefined>;
79
154
  /**
80
155
  * What a provider can offer as an interactive login: an OAuth flow, an API-key ENTRY prompt, or nothing ("none" — the
81
156
  * key must come from the provider's env var).
@@ -84,7 +159,7 @@ export type InteractiveLoginKind = "oauth" | "api_key" | "none";
84
159
  export declare function interactiveLoginKind(p: Provider): InteractiveLoginKind;
85
160
  /** THE rule for "can this method be signed in to interactively": the auth to run for it, or undefined. */
86
161
  export declare function interactiveAuth(provider: Provider, method: Exclude<InteractiveLoginKind, "none">): import("@earendil-works/pi-ai").ApiKeyAuth | import("@earendil-works/pi-ai").OAuthAuth | undefined;
87
- /** The providers a sign-in can target: pi's built-ins plus `extra`, composed exactly as {@link createPiModels} does. */
162
+ /** The providers a sign-in can target: pi's built-ins plus `extra`, composed exactly as {@link piModelsOver} does. */
88
163
  export declare function loginProviders(extra?: readonly Provider[]): readonly Provider[];
89
164
  /** Per-provider auth status for the first-run model picker. */
90
165
  export type ProviderAuthStatus = {
@@ -100,7 +175,11 @@ export type ProviderAuthStatus = {
100
175
  };
101
176
  /** Probe every provider's auth once (auth is provider-scoped, so any of its models works as the probe). */
102
177
  export declare function providerAuthStatuses(models: Models): Promise<Map<string, ProviderAuthStatus>>;
103
- /** Which source currently satisfies auth for `spec` — a startup diagnostic. */
178
+ /**
179
+ * Which source currently satisfies auth for `spec`, or undefined when none does (or the spec is not in `models`).
180
+ * Rejects when resolving fails — a corrupt entry, a refresh the provider refused — which is a different answer from
181
+ * "nothing configured" and must reach whoever reports it.
182
+ */
104
183
  export declare function probeAuthSource(models: Models, spec: string): Promise<string | undefined>;
105
184
  /**
106
185
  * Verdict of {@link probeApiKey}: `rejected` is DEFINITIVE (the provider answered HTTP 401 — the key is wrong);