@fastagent-sh/fastagent 0.22.0 → 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.
- package/dist/channels/agentcore-protocol.d.ts +2 -1
- package/dist/channels/agentcore-service.js +10 -18
- package/dist/channels/agentcore.js +6 -3
- package/dist/channels/control.js +23 -0
- package/dist/channels/slack/config-api.d.ts +2 -2
- package/dist/channels/slack/config-api.js +2 -2
- package/dist/channels/slack/onboard.js +2 -2
- package/dist/channels/slack/register-webhook.js +2 -2
- package/dist/channels/slack/slack-api.js +4 -4
- package/dist/cli/add-feishu.js +4 -2
- package/dist/cli/auth-view.d.ts +15 -6
- package/dist/cli/auth-view.js +24 -8
- package/dist/cli/box-login.d.ts +33 -0
- package/dist/cli/box-login.js +162 -0
- package/dist/cli/commands/deploy/agentcore.js +48 -11
- package/dist/cli/commands/deploy/docker.js +24 -13
- package/dist/cli/commands/deploy/fly.js +30 -7
- package/dist/cli/commands/deploy/railway.js +21 -7
- package/dist/cli/commands/deploy/shared.d.ts +18 -17
- package/dist/cli/commands/deploy/shared.js +20 -21
- package/dist/cli/commands/destroy.js +2 -2
- package/dist/cli/commands/info.js +9 -6
- package/dist/cli/commands/invoke.js +2 -2
- package/dist/cli/commands/login.d.ts +7 -1
- package/dist/cli/commands/login.js +123 -10
- package/dist/cli/commands/logs.js +2 -2
- package/dist/cli/commands/models.d.ts +4 -1
- package/dist/cli/commands/models.js +37 -4
- package/dist/cli/commands/routine-run.js +2 -2
- package/dist/cli/commands/start.d.ts +0 -5
- package/dist/cli/commands/start.js +3 -13
- package/dist/cli/kernel.d.ts +2 -0
- package/dist/cli/kernel.js +1 -1
- package/dist/cli/login-relay.d.ts +38 -0
- package/dist/cli/login-relay.js +121 -0
- package/dist/cli/program.js +46 -8
- package/dist/cli/shared.d.ts +4 -4
- package/dist/cli/shared.js +24 -30
- package/dist/deploy/agentcore/plan.d.ts +10 -11
- package/dist/deploy/agentcore/plan.js +8 -14
- package/dist/deploy/agentcore/run.d.ts +8 -1
- package/dist/deploy/agentcore/run.js +20 -14
- package/dist/deploy/agentcore/shell.d.ts +25 -0
- package/dist/deploy/agentcore/shell.js +202 -0
- package/dist/deploy/box-shell.d.ts +43 -0
- package/dist/deploy/box-shell.js +28 -0
- package/dist/deploy/build-context.js +16 -7
- package/dist/deploy/channel-ingress.d.ts +20 -1
- package/dist/deploy/channel-ingress.js +34 -7
- package/dist/deploy/container.d.ts +14 -0
- package/dist/deploy/container.js +45 -1
- package/dist/deploy/docker/plan.d.ts +7 -3
- package/dist/deploy/docker/plan.js +9 -14
- package/dist/deploy/docker/run.d.ts +14 -7
- package/dist/deploy/docker/run.js +58 -35
- package/dist/deploy/fly/plan.d.ts +6 -3
- package/dist/deploy/fly/plan.js +6 -8
- package/dist/deploy/fly/run.d.ts +8 -2
- package/dist/deploy/fly/run.js +15 -25
- package/dist/deploy/preflight.d.ts +9 -7
- package/dist/deploy/preflight.js +74 -20
- package/dist/deploy/railway/plan.d.ts +6 -3
- package/dist/deploy/railway/plan.js +7 -9
- package/dist/deploy/railway/run.d.ts +10 -6
- package/dist/deploy/railway/run.js +29 -13
- package/dist/deploy/runner.d.ts +16 -0
- package/dist/deploy/runner.js +31 -0
- package/dist/deploy/secrets.d.ts +4 -13
- package/dist/deploy/secrets.js +8 -27
- package/dist/dev-supervisor.js +5 -2
- package/dist/engines/pi/agent-models.d.ts +70 -0
- package/dist/engines/pi/agent-models.js +93 -0
- package/dist/engines/pi/auth.d.ts +56 -3
- package/dist/engines/pi/auth.js +63 -16
- package/dist/engines/pi/config.d.ts +0 -25
- package/dist/engines/pi/config.js +3 -37
- package/dist/engines/pi/create.d.ts +22 -16
- package/dist/engines/pi/create.js +28 -28
- package/dist/engines/pi/entry-images.d.ts +14 -0
- package/dist/engines/pi/entry-images.js +23 -0
- package/dist/engines/pi/invoke-session.js +26 -0
- package/dist/engines/pi/login.d.ts +20 -13
- package/dist/engines/pi/login.js +19 -12
- package/dist/engines/pi/models.d.ts +115 -36
- package/dist/engines/pi/models.js +218 -48
- package/dist/engines/pi/open.d.ts +42 -11
- package/dist/engines/pi/open.js +53 -21
- package/dist/engines/pi/service.d.ts +2 -2
- package/dist/engines/pi/service.js +1 -0
- package/dist/engines/pi/session-builder.d.ts +3 -2
- package/dist/engines/pi/session-builder.js +28 -58
- package/dist/engines/pi/session-control.js +14 -3
- package/dist/engines/pi/turn-kit.js +11 -5
- package/dist/open-url.d.ts +15 -1
- package/dist/open-url.js +35 -3
- package/dist/paths.d.ts +4 -2
- package/dist/paths.js +6 -2
- package/dist/pi.d.ts +5 -3
- package/dist/pi.js +3 -2
- package/dist/service.d.ts +5 -8
- package/dist/session-remote.js +21 -0
- package/dist/session.d.ts +39 -6
- package/package.json +2 -1
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { contentText } from "@earendil-works/pi-ai";
|
|
1
2
|
import * as Deferred from "effect/Deferred";
|
|
2
3
|
import * as Effect from "effect/Effect";
|
|
3
4
|
import * as Fiber from "effect/Fiber";
|
|
4
5
|
import * as Queue from "effect/Queue";
|
|
5
6
|
import { ABORTED_CODE, SESSION_BUSY_CODE, } from "../../agent.js";
|
|
7
|
+
import { entryImages } from "./entry-images.js";
|
|
6
8
|
import { cancellableStream } from "../../collect.js";
|
|
7
9
|
import { log } from "../../log.js";
|
|
8
10
|
import { toRetryScheduledEvent } from "./retry-event.js";
|
|
@@ -91,6 +93,29 @@ function trackExtensionTurns(session) {
|
|
|
91
93
|
session.sendCustomMessage = (...args) => track(sendCustomMessage(...args));
|
|
92
94
|
return pending;
|
|
93
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Report each user message when it is WRITTEN, which is later than pi announces it: pi awaits extension `message_end`
|
|
98
|
+
* handlers before it appends. Emitting from the write is what makes `user_message.entryId` readable through
|
|
99
|
+
* `entries()` by the time the event arrives, so a reconnecting client's backfill cannot miss a message whose event
|
|
100
|
+
* fired before it subscribed. pi's agent awaits each listener before the next event, so the message still reports
|
|
101
|
+
* before the answer to it. The in-memory store reuses one record across runs, so the release restores the method.
|
|
102
|
+
*/
|
|
103
|
+
function reportUserMessages(session, report) {
|
|
104
|
+
const record = session.sessionManager;
|
|
105
|
+
const append = record.appendMessage;
|
|
106
|
+
return Effect.acquireRelease(Effect.sync(() => {
|
|
107
|
+
record.appendMessage = (message) => {
|
|
108
|
+
const entryId = append.call(record, message);
|
|
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
|
+
}
|
|
113
|
+
return entryId;
|
|
114
|
+
};
|
|
115
|
+
}), () => Effect.sync(() => {
|
|
116
|
+
record.appendMessage = append;
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
94
119
|
export function createPiAgentFromSession(options) {
|
|
95
120
|
const { sessionFactory, lease = inProcessLease(), observer } = options;
|
|
96
121
|
async function* turn(scope, prompt, { onCancelReady, wasCancelled }) {
|
|
@@ -217,6 +242,7 @@ export function createPiAgentFromSession(options) {
|
|
|
217
242
|
if (OWED_BY_THE_RUN.has(error.event))
|
|
218
243
|
extensionFailure ??= `${error.event} failed (${error.extensionPath}): ${error.error}`;
|
|
219
244
|
})), (unsubscribe) => Effect.sync(unsubscribe));
|
|
245
|
+
yield* reportUserMessages(session, (data) => observe({ type: "user_message", timestamp: Date.now(), runId, data }));
|
|
220
246
|
const extensionTurns = trackExtensionTurns(session);
|
|
221
247
|
// Completing the gate can run waiting controls synchronously; their queue events must be observed.
|
|
222
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
|
|
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 `
|
|
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(
|
|
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(
|
|
33
|
-
export
|
|
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
|
|
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
|
package/dist/engines/pi/login.js
CHANGED
|
@@ -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 `
|
|
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(
|
|
18
|
-
return loginOptionsOver(
|
|
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(
|
|
22
|
-
// ONE read of the
|
|
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
|
|
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
|
|
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,
|
|
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 =
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
|
49
|
-
* `deploy` must judge by:
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
|
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
|
-
/**
|
|
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);
|