@oh-my-pi/pi-ai 17.2.5 → 17.2.6
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/CHANGELOG.md +10 -0
- package/dist/types/dialect/examples.d.ts +8 -0
- package/dist/types/error/aws.d.ts +5 -1
- package/dist/types/providers/aws-credentials.d.ts +5 -10
- package/dist/types/providers/bedrock-mantle.d.ts +13 -0
- package/dist/types/registry/amazon-bedrock.d.ts +7 -1
- package/dist/types/registry/aws.d.ts +13 -0
- package/dist/types/registry/bedrock-mantle.d.ts +22 -0
- package/dist/types/registry/registry.d.ts +25 -1
- package/dist/types/registry/types.d.ts +24 -0
- package/dist/types/types.d.ts +5 -0
- package/dist/types/utils/aws-profile.d.ts +17 -0
- package/package.json +4 -4
- package/src/auth-broker/wire-schema-resource.ts +6 -1
- package/src/dialect/examples.ts +34 -8
- package/src/dialect/inventory.ts +2 -2
- package/src/error/aws.ts +5 -1
- package/src/providers/amazon-bedrock.ts +5 -5
- package/src/providers/aws-credentials.ts +262 -76
- package/src/providers/bedrock-mantle.ts +110 -0
- package/src/providers/ollama.ts +27 -1
- package/src/registry/amazon-bedrock.ts +9 -14
- package/src/registry/aws.ts +57 -0
- package/src/registry/bedrock-mantle.ts +34 -0
- package/src/registry/google-vertex.ts +2 -2
- package/src/registry/registry.ts +2 -0
- package/src/registry/types.ts +30 -0
- package/src/stream.ts +46 -30
- package/src/types.ts +5 -0
- package/src/utils/aws-profile.ts +88 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [17.2.6] - 2026-08-03
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added profile-aware Bedrock Mantle region selection, authenticated model discovery, bearer-token or SigV4 authentication, and credential refresh handling for OpenAI Responses models.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Fixed an issue where Ollama requests without a user-role message would fail to generate output or silently fail with a misleading error.
|
|
14
|
+
|
|
5
15
|
## [17.2.5] - 2026-08-03
|
|
6
16
|
|
|
7
17
|
### Changed
|
|
@@ -8,3 +8,11 @@ import type { InbandTool } from "./types.js";
|
|
|
8
8
|
* tool, and payload args (commands, code, patches) read best verbatim.
|
|
9
9
|
*/
|
|
10
10
|
export declare function renderToolExamples(tool: InbandTool, intentField?: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Render a tool's examples as JSDoc-style `@example` lines for comment-gutter
|
|
13
|
+
* contexts (the Harmony `namespace functions` inventory): `@example "caption"`
|
|
14
|
+
* followed by the call in the same Python kwargs syntax as the wire block. The
|
|
15
|
+
* tag line delimits each example, so no XML envelope is needed — which is why
|
|
16
|
+
* the inventory uses this instead of `//`-prefixing the `<examples>` block.
|
|
17
|
+
*/
|
|
18
|
+
export declare function renderToolExamplesJsdoc(tool: InbandTool): string;
|
|
@@ -9,7 +9,11 @@ export type AwsCredentialsErrorKind =
|
|
|
9
9
|
/** SSO `GetRoleCredentials` call failed or returned no role. */
|
|
10
10
|
| "sso-role"
|
|
11
11
|
/** External `credential_process` failed, timed out, or emitted bad output. */
|
|
12
|
-
| "credential-process"
|
|
12
|
+
| "credential-process"
|
|
13
|
+
/** STS web-identity exchange failed or returned malformed credentials. */
|
|
14
|
+
| "web-identity"
|
|
15
|
+
/** ECS/container credential endpoint failed or returned malformed credentials. */
|
|
16
|
+
| "container";
|
|
13
17
|
/** A failure resolving AWS credentials for the Bedrock provider. */
|
|
14
18
|
export declare class AwsCredentialsError extends Error {
|
|
15
19
|
readonly kind: AwsCredentialsErrorKind;
|
|
@@ -4,16 +4,11 @@
|
|
|
4
4
|
* Chain (first hit wins):
|
|
5
5
|
* 1. Static credentials from the environment
|
|
6
6
|
* (`AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY` [+ `AWS_SESSION_TOKEN`]).
|
|
7
|
-
* 2.
|
|
8
|
-
*
|
|
9
|
-
* -
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* - `credential_process` — an external command emitting the AWS SDK
|
|
13
|
-
* `Version: 1` JSON envelope on stdout. Used by `aws-vault`, `granted`,
|
|
14
|
-
* in-house brokers, etc.
|
|
15
|
-
* 3. EC2 IMDSv2 (only when `AWS_EC2_METADATA_DISABLED` is unset / falsey and
|
|
16
|
-
* `169.254.169.254` is reachable within a 1 s timeout).
|
|
7
|
+
* 2. Web identity (`AWS_WEB_IDENTITY_TOKEN_FILE` + `AWS_ROLE_ARN`).
|
|
8
|
+
* 3. Profile in `~/.aws/credentials` (and `~/.aws/config` for SSO):
|
|
9
|
+
* - static keys, SSO, or `credential_process`.
|
|
10
|
+
* 4. ECS/container credentials from `AWS_CONTAINER_CREDENTIALS_*`.
|
|
11
|
+
* 5. EC2 IMDSv2 when metadata is enabled.
|
|
17
12
|
*
|
|
18
13
|
* Resolved credentials are cached process-wide per profile and refreshed
|
|
19
14
|
* 60 s before `Expiration` to absorb clock skew.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type AwsBedrockProviderOptions } from "../registry/aws.js";
|
|
2
|
+
import type { FetchImpl, Model } from "../types.js";
|
|
3
|
+
import type { OpenAIResponsesOptions } from "./openai-responses.js";
|
|
4
|
+
export type BedrockMantleProviderOptions = AwsBedrockProviderOptions;
|
|
5
|
+
export interface BedrockMantleOptions extends OpenAIResponsesOptions {
|
|
6
|
+
providerOptions?: BedrockMantleProviderOptions;
|
|
7
|
+
}
|
|
8
|
+
export declare function createBedrockMantleAuthenticatedFetch(options?: BedrockMantleOptions): FetchImpl;
|
|
9
|
+
export interface PreparedBedrockMantleRequest {
|
|
10
|
+
model: Model<"openai-responses">;
|
|
11
|
+
options: OpenAIResponsesOptions;
|
|
12
|
+
}
|
|
13
|
+
export declare function prepareBedrockMantleRequest(model: Model<"openai-responses">, options: BedrockMantleOptions): PreparedBedrockMantleRequest;
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
import { resolveAwsRegistryApiKey } from "./aws.js";
|
|
1
2
|
export declare const amazonBedrockProvider: {
|
|
2
3
|
readonly id: "amazon-bedrock";
|
|
3
4
|
readonly name: "Amazon Bedrock";
|
|
4
|
-
readonly envKeys:
|
|
5
|
+
readonly envKeys: typeof resolveAwsRegistryApiKey;
|
|
6
|
+
readonly mapSimpleOptions: (options: import("../index.js").SimpleStreamOptions) => {
|
|
7
|
+
region: string | undefined;
|
|
8
|
+
profile: string | undefined;
|
|
9
|
+
bearerToken: string | undefined;
|
|
10
|
+
};
|
|
5
11
|
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface AwsBedrockProviderOptions extends Readonly<Record<string, unknown>> {
|
|
2
|
+
/** AWS region used in the service endpoint and SigV4 credential scope. */
|
|
3
|
+
region?: string;
|
|
4
|
+
/** Named AWS shared-credentials/config profile. */
|
|
5
|
+
profile?: string;
|
|
6
|
+
/** Amazon Bedrock API key sent as a bearer token, ahead of SigV4 credential resolution. */
|
|
7
|
+
bearerToken?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function hasAwsCredentialSource(): boolean;
|
|
10
|
+
/** Registry key marker for AWS transports that resolve their own bearer/IAM credentials. */
|
|
11
|
+
export declare function resolveAwsRegistryApiKey(): string | undefined;
|
|
12
|
+
/** Resolve a real AWS bearer token while filtering the registry's auth marker. */
|
|
13
|
+
export declare function resolveAwsBearerToken(apiKey?: string, bearerToken?: string): string | undefined;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Model } from "../types.js";
|
|
2
|
+
import { resolveAwsRegistryApiKey } from "./aws.js";
|
|
3
|
+
export declare const bedrockMantleProvider: {
|
|
4
|
+
readonly id: "bedrock-mantle";
|
|
5
|
+
readonly name: "Amazon Bedrock Mantle";
|
|
6
|
+
readonly envKeys: typeof resolveAwsRegistryApiKey;
|
|
7
|
+
readonly allowsMissingApiKey: true;
|
|
8
|
+
readonly prepareRequest: (model: Model<import("@oh-my-pi/pi-catalog").Api>, options: import("../index.js").StreamOptions) => import("../providers/bedrock-mantle.js").PreparedBedrockMantleRequest;
|
|
9
|
+
readonly mapSimpleOptions: (options: import("../index.js").SimpleStreamOptions) => {
|
|
10
|
+
providerOptions: Readonly<Record<string, unknown>> | undefined;
|
|
11
|
+
};
|
|
12
|
+
readonly prepareModelDiscovery: (config: import("./types.js").ProviderModelDiscoveryConfig) => {
|
|
13
|
+
baseUrl?: string;
|
|
14
|
+
fetch?: import("@oh-my-pi/pi-utils").FetchImpl;
|
|
15
|
+
apiKey: undefined;
|
|
16
|
+
authenticated: false;
|
|
17
|
+
} | {
|
|
18
|
+
authenticated: true;
|
|
19
|
+
baseUrl: string;
|
|
20
|
+
fetch: import("@oh-my-pi/pi-utils").FetchImpl;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
@@ -25,7 +25,12 @@ declare const ALL: ({
|
|
|
25
25
|
} | {
|
|
26
26
|
readonly id: "amazon-bedrock";
|
|
27
27
|
readonly name: "Amazon Bedrock";
|
|
28
|
-
readonly envKeys: (
|
|
28
|
+
readonly envKeys: typeof import("./aws.js").resolveAwsRegistryApiKey;
|
|
29
|
+
readonly mapSimpleOptions: (options: import("../index.js").SimpleStreamOptions) => {
|
|
30
|
+
region: string | undefined;
|
|
31
|
+
profile: string | undefined;
|
|
32
|
+
bearerToken: string | undefined;
|
|
33
|
+
};
|
|
29
34
|
} | {
|
|
30
35
|
readonly id: "anthropic";
|
|
31
36
|
readonly name: "Anthropic (Claude Pro/Max)";
|
|
@@ -41,6 +46,25 @@ declare const ALL: ({
|
|
|
41
46
|
readonly id: "baseten";
|
|
42
47
|
readonly name: "Baseten";
|
|
43
48
|
readonly login: (cb: import("./oauth/index.js").OAuthLoginCallbacks) => Promise<string>;
|
|
49
|
+
} | {
|
|
50
|
+
readonly id: "bedrock-mantle";
|
|
51
|
+
readonly name: "Amazon Bedrock Mantle";
|
|
52
|
+
readonly envKeys: typeof import("./aws.js").resolveAwsRegistryApiKey;
|
|
53
|
+
readonly allowsMissingApiKey: true;
|
|
54
|
+
readonly prepareRequest: (model: import("@oh-my-pi/pi-catalog").Model<import("@oh-my-pi/pi-catalog").Api>, options: import("../index.js").StreamOptions) => import("../providers/bedrock-mantle.js").PreparedBedrockMantleRequest;
|
|
55
|
+
readonly mapSimpleOptions: (options: import("../index.js").SimpleStreamOptions) => {
|
|
56
|
+
providerOptions: Readonly<Record<string, unknown>> | undefined;
|
|
57
|
+
};
|
|
58
|
+
readonly prepareModelDiscovery: (config: import("./types.js").ProviderModelDiscoveryConfig) => {
|
|
59
|
+
baseUrl?: string;
|
|
60
|
+
fetch?: import("@oh-my-pi/pi-utils").FetchImpl;
|
|
61
|
+
apiKey: undefined;
|
|
62
|
+
authenticated: false;
|
|
63
|
+
} | {
|
|
64
|
+
authenticated: true;
|
|
65
|
+
baseUrl: string;
|
|
66
|
+
fetch: import("@oh-my-pi/pi-utils").FetchImpl;
|
|
67
|
+
};
|
|
44
68
|
} | {
|
|
45
69
|
readonly id: "cerebras";
|
|
46
70
|
readonly name: "Cerebras";
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* (default model, model-manager factory, catalog discovery) lives in
|
|
10
10
|
* `@oh-my-pi/pi-catalog`'s descriptor table.
|
|
11
11
|
*/
|
|
12
|
+
import type { Api, FetchImpl, Model, SimpleStreamOptions, StreamOptions } from "../types.js";
|
|
12
13
|
import type { OAuthCredentials, OAuthLoginCallbacks } from "./oauth/types.js";
|
|
13
14
|
/**
|
|
14
15
|
* API-key environment fallback: either a single env var name (e.g.
|
|
@@ -16,6 +17,21 @@ import type { OAuthCredentials, OAuthLoginCallbacks } from "./oauth/types.js";
|
|
|
16
17
|
* the host (Vertex ADC, Bedrock credential chains, …).
|
|
17
18
|
*/
|
|
18
19
|
export type KeyResolver = string | (() => string | undefined);
|
|
20
|
+
/** Credentials are resolved by the provider transport rather than used as a bearer string. */
|
|
21
|
+
export declare const AUTHENTICATED_SENTINEL = "<authenticated>";
|
|
22
|
+
export interface PreparedProviderRequest {
|
|
23
|
+
readonly model: Model<Api>;
|
|
24
|
+
readonly options: StreamOptions;
|
|
25
|
+
}
|
|
26
|
+
export type ProviderRequestPreparer = (model: Model<Api>, options: StreamOptions) => PreparedProviderRequest;
|
|
27
|
+
export type ProviderSimpleOptionsMapper = (options: SimpleStreamOptions) => Readonly<Record<string, unknown>>;
|
|
28
|
+
export interface ProviderModelDiscoveryConfig {
|
|
29
|
+
readonly apiKey?: string;
|
|
30
|
+
readonly baseUrl?: string;
|
|
31
|
+
readonly fetch?: FetchImpl;
|
|
32
|
+
readonly authenticated?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export type ProviderModelDiscoveryPreparer = (config: ProviderModelDiscoveryConfig) => ProviderModelDiscoveryConfig;
|
|
19
35
|
/**
|
|
20
36
|
* Declarative description of a single provider's auth/login wiring. All
|
|
21
37
|
* fields are optional except `id`/`name`; presence of a field opts the
|
|
@@ -39,6 +55,14 @@ export interface ProviderDefinition {
|
|
|
39
55
|
/** Whether to surface in the interactive login list. Defaults to true when `login` is present. */
|
|
40
56
|
readonly showInLoginList?: boolean;
|
|
41
57
|
readonly envKeys?: KeyResolver;
|
|
58
|
+
/** Provider transport can authenticate without a resolved API-key string. */
|
|
59
|
+
readonly allowsMissingApiKey?: boolean;
|
|
60
|
+
/** Provider-owned request shaping applied before generic API dispatch. */
|
|
61
|
+
readonly prepareRequest?: ProviderRequestPreparer;
|
|
62
|
+
/** Provider-owned projection from the generic simple-stream option bag. */
|
|
63
|
+
readonly mapSimpleOptions?: ProviderSimpleOptionsMapper;
|
|
64
|
+
/** Provider-owned authentication and endpoint setup for model discovery. */
|
|
65
|
+
readonly prepareModelDiscovery?: ProviderModelDiscoveryPreparer;
|
|
42
66
|
readonly login?: (callbacks: OAuthLoginCallbacks) => Promise<OAuthCredentials | string>;
|
|
43
67
|
readonly refreshToken?: (credentials: OAuthCredentials) => Promise<OAuthCredentials>;
|
|
44
68
|
readonly getApiKey?: (credentials: OAuthCredentials) => string;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -249,6 +249,11 @@ export interface StreamOptions {
|
|
|
249
249
|
* For example, Anthropic uses `user_id` for abuse tracking and rate limiting.
|
|
250
250
|
*/
|
|
251
251
|
metadata?: Record<string, unknown>;
|
|
252
|
+
/**
|
|
253
|
+
* Provider-owned request configuration. Provider hooks interpret this bag;
|
|
254
|
+
* generic API transports do not forward its fields onto the wire.
|
|
255
|
+
*/
|
|
256
|
+
providerOptions?: Readonly<Record<string, unknown>>;
|
|
252
257
|
/** OpenAI Responses/Codex response fields to include verbatim. */
|
|
253
258
|
include?: OpenAIResponseInclude[];
|
|
254
259
|
/**
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** INI sections with `profile ` / `sso-session ` prefixes normalized. */
|
|
2
|
+
export type AwsIniFile = Record<string, Record<string, string>>;
|
|
3
|
+
export declare function parseAwsIni(text: string): AwsIniFile;
|
|
4
|
+
/** Resolve the selected shared-credentials profile. */
|
|
5
|
+
export declare function resolveAwsProfile(profile?: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Whether the shared config file participates in profile/region resolution.
|
|
8
|
+
* Explicit profile selection enables it; the implicit default profile follows
|
|
9
|
+
* the AWS SDK's `AWS_SDK_LOAD_CONFIG` opt-in.
|
|
10
|
+
*/
|
|
11
|
+
export declare function shouldLoadAwsSharedConfig(profile?: string): boolean;
|
|
12
|
+
export declare function resolveAwsProfileRegion(profile?: string): string | undefined;
|
|
13
|
+
/** Region selected by the environment or active shared-config profile. */
|
|
14
|
+
export declare function resolveAwsAmbientRegion(profile?: string): string | undefined;
|
|
15
|
+
/** Resolve the region precedence shared by AWS transports and credential exchanges. */
|
|
16
|
+
export declare function resolveAwsRegion(explicitRegion?: string, profile?: string): string;
|
|
17
|
+
export declare function hasConfiguredAwsProfile(profile?: string): boolean;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-ai",
|
|
4
|
-
"version": "17.2.
|
|
4
|
+
"version": "17.2.6",
|
|
5
5
|
"description": "Unified LLM API with automatic model discovery and provider configuration",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@bufbuild/protobuf": "^2.12.1",
|
|
41
|
-
"@oh-my-pi/pi-catalog": "17.2.
|
|
42
|
-
"@oh-my-pi/pi-utils": "17.2.
|
|
43
|
-
"@oh-my-pi/pi-wire": "17.2.
|
|
41
|
+
"@oh-my-pi/pi-catalog": "17.2.6",
|
|
42
|
+
"@oh-my-pi/pi-utils": "17.2.6",
|
|
43
|
+
"@oh-my-pi/pi-wire": "17.2.6",
|
|
44
44
|
"arktype": "2.2.3",
|
|
45
45
|
"zod": "^4"
|
|
46
46
|
},
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* exception (standard type keeps extra keys): it preserves provider-specific extension fields so
|
|
13
13
|
* they round-trip through the broker instead of being dropped (see below).
|
|
14
14
|
*/
|
|
15
|
-
import { type Type
|
|
15
|
+
import { scope, type Type } from "arktype";
|
|
16
16
|
import {
|
|
17
17
|
type ApiKeyCredential,
|
|
18
18
|
type AuthCredential,
|
|
@@ -84,6 +84,11 @@ export interface AuthBrokerWireSchemas {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
function buildAuthBrokerWireSchemas(): AuthBrokerWireSchemas {
|
|
87
|
+
// Wire schemas validate only a handful of times per process, so ArkType's
|
|
88
|
+
// definition-time JIT codegen is startup tax. A local jitless scope skips
|
|
89
|
+
// that codegen and uses interpreted traversal; correctness is unchanged.
|
|
90
|
+
const { type } = scope({}, { jitless: true });
|
|
91
|
+
|
|
87
92
|
// ─── Credential payloads ───────────────────────────────────────────────────
|
|
88
93
|
|
|
89
94
|
/** Real OAuth credential (broker-side) — refresh token is the actual upstream value. */
|
package/src/dialect/examples.ts
CHANGED
|
@@ -15,17 +15,12 @@ export function renderToolExamples(tool: InbandTool, intentField?: string): stri
|
|
|
15
15
|
const examples = tool.examples;
|
|
16
16
|
if (!examples?.length) return "";
|
|
17
17
|
const renderCall = (args: Record<string, unknown>): string => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
for (const key in args) {
|
|
21
|
-
argCount++;
|
|
22
|
-
soleKey = key;
|
|
23
|
-
}
|
|
24
|
-
if (argCount === 1 && soleKey !== undefined && typeof args[soleKey] === "string") {
|
|
18
|
+
const bare = bareStringArg(args);
|
|
19
|
+
if (bare !== undefined) {
|
|
25
20
|
// Bare payload. The intent placeholder still rides on the envelope so
|
|
26
21
|
// intent-traced schemas (where `i` is required) keep teaching it.
|
|
27
22
|
const intentAttr = intentField ? ` ${intentField}="${INTENT_PLACEHOLDER}"` : "";
|
|
28
|
-
return `<example${intentAttr}>\n${
|
|
23
|
+
return `<example${intentAttr}>\n${bare}\n</example>`;
|
|
29
24
|
}
|
|
30
25
|
// When intent tracing injects `i` into the schema, examples must show a
|
|
31
26
|
// placeholder so the model learns to emit it. Keep it first, matching the
|
|
@@ -43,3 +38,34 @@ export function renderToolExamples(tool: InbandTool, intentField?: string): stri
|
|
|
43
38
|
});
|
|
44
39
|
return `<examples>\n${parts.join("\n")}\n</examples>`;
|
|
45
40
|
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Render a tool's examples as JSDoc-style `@example` lines for comment-gutter
|
|
44
|
+
* contexts (the Harmony `namespace functions` inventory): `@example "caption"`
|
|
45
|
+
* followed by the call in the same Python kwargs syntax as the wire block. The
|
|
46
|
+
* tag line delimits each example, so no XML envelope is needed — which is why
|
|
47
|
+
* the inventory uses this instead of `//`-prefixing the `<examples>` block.
|
|
48
|
+
*/
|
|
49
|
+
export function renderToolExamplesJsdoc(tool: InbandTool): string {
|
|
50
|
+
const examples = tool.examples;
|
|
51
|
+
if (!examples?.length) return "";
|
|
52
|
+
const renderCall = (args: Record<string, unknown>): string => bareStringArg(args) ?? pyCall(tool.name, args);
|
|
53
|
+
const parts = examples.map(ex => {
|
|
54
|
+
const head = ex.caption ? `@example ${JSON.stringify(ex.caption)}` : "@example";
|
|
55
|
+
if ("call" in ex) return `${head}\n${renderCall(ex.call)}`;
|
|
56
|
+
if ("good" in ex) return `${head}\nWRONG:\n${renderCall(ex.bad)}\nRIGHT:\n${renderCall(ex.good)}`;
|
|
57
|
+
return ex.note ? `${head}\n${ex.note}` : head;
|
|
58
|
+
});
|
|
59
|
+
return parts.join("\n");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Sole-argument string payload, if the call has exactly one string argument. */
|
|
63
|
+
function bareStringArg(args: Record<string, unknown>): string | undefined {
|
|
64
|
+
let sole: unknown;
|
|
65
|
+
let count = 0;
|
|
66
|
+
for (const key in args) {
|
|
67
|
+
count++;
|
|
68
|
+
sole = args[key];
|
|
69
|
+
}
|
|
70
|
+
return count === 1 && typeof sole === "string" ? sole : undefined;
|
|
71
|
+
}
|
package/src/dialect/inventory.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsonSchemaToTypeScript, toolWireSchema } from "../utils/schema";
|
|
2
|
-
import {
|
|
2
|
+
import { renderToolExamplesJsdoc } from "./examples";
|
|
3
3
|
import type { InbandTool } from "./types";
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -18,7 +18,7 @@ export function renderToolInventory(tools: readonly InbandTool[]): string {
|
|
|
18
18
|
if (description) {
|
|
19
19
|
for (const line of description.split("\n")) lines.push(`// ${line}`.trimEnd());
|
|
20
20
|
}
|
|
21
|
-
const examples =
|
|
21
|
+
const examples = renderToolExamplesJsdoc(tool);
|
|
22
22
|
if (examples) {
|
|
23
23
|
if (description) lines.push("//");
|
|
24
24
|
for (const line of examples.split("\n")) lines.push(`// ${line}`.trimEnd());
|
package/src/error/aws.ts
CHANGED
|
@@ -9,7 +9,11 @@ export type AwsCredentialsErrorKind =
|
|
|
9
9
|
/** SSO `GetRoleCredentials` call failed or returned no role. */
|
|
10
10
|
| "sso-role"
|
|
11
11
|
/** External `credential_process` failed, timed out, or emitted bad output. */
|
|
12
|
-
| "credential-process"
|
|
12
|
+
| "credential-process"
|
|
13
|
+
/** STS web-identity exchange failed or returned malformed credentials. */
|
|
14
|
+
| "web-identity"
|
|
15
|
+
/** ECS/container credential endpoint failed or returned malformed credentials. */
|
|
16
|
+
| "container";
|
|
13
17
|
|
|
14
18
|
/** A failure resolving AWS credentials for the Bedrock provider. */
|
|
15
19
|
export class AwsCredentialsError extends Error {
|
|
@@ -10,9 +10,10 @@
|
|
|
10
10
|
import type { Effort } from "@oh-my-pi/pi-catalog/effort";
|
|
11
11
|
import { mapEffortToAnthropicAdaptiveEffort, requireSupportedEffort } from "@oh-my-pi/pi-catalog/model-thinking";
|
|
12
12
|
import { calculateCost } from "@oh-my-pi/pi-catalog/models";
|
|
13
|
-
import { $
|
|
13
|
+
import { $flag, fetchWithRetry, parseStreamingJson, parseStreamingJsonThrottled } from "@oh-my-pi/pi-utils";
|
|
14
14
|
import { renderDemotedThinking } from "../dialect/demotion";
|
|
15
15
|
import * as AIError from "../error";
|
|
16
|
+
import { resolveAwsBearerToken } from "../registry/aws";
|
|
16
17
|
import type {
|
|
17
18
|
Api,
|
|
18
19
|
AssistantMessage,
|
|
@@ -30,6 +31,7 @@ import type {
|
|
|
30
31
|
ToolResultMessage,
|
|
31
32
|
} from "../types";
|
|
32
33
|
import { normalizeSystemPrompts, normalizeToolCallId, resolveCacheRetention } from "../utils";
|
|
34
|
+
import { resolveAwsAmbientRegion } from "../utils/aws-profile";
|
|
33
35
|
import {
|
|
34
36
|
clearStreamingPartialJson,
|
|
35
37
|
kStreamingBlockIndex,
|
|
@@ -74,11 +76,9 @@ export interface BedrockOptions extends StreamOptions {
|
|
|
74
76
|
*/
|
|
75
77
|
thinkingDisplay?: BedrockThinkingDisplay;
|
|
76
78
|
}
|
|
77
|
-
const AUTHENTICATED_API_KEY_SENTINEL = "<authenticated>";
|
|
78
79
|
|
|
79
80
|
function resolveBearerToken(options: BedrockOptions): string | undefined {
|
|
80
|
-
|
|
81
|
-
return options.bearerToken || apiKey || $env.AWS_BEARER_TOKEN_BEDROCK;
|
|
81
|
+
return resolveAwsBearerToken(options.apiKey, options.bearerToken);
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
function inferRegionFromBedrockArn(modelId: string): string | undefined {
|
|
@@ -149,7 +149,7 @@ function regionServesGeo(region: string, geo: string): boolean {
|
|
|
149
149
|
function resolveBedrockRegion(modelId: string, options: BedrockOptions): string {
|
|
150
150
|
const explicit = options.region || inferRegionFromBedrockArn(modelId);
|
|
151
151
|
if (explicit) return explicit;
|
|
152
|
-
const ambient =
|
|
152
|
+
const ambient = resolveAwsAmbientRegion(options.profile);
|
|
153
153
|
const geo = inferenceProfileGeo(modelId);
|
|
154
154
|
if (geo) {
|
|
155
155
|
if (ambient && regionServesGeo(ambient, geo)) return ambient;
|