@genesislcap/foundation-ai 15.40.0 → 15.41.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 +21 -0
- package/dist/dts/index.d.ts +2 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/transports/ai-service-error.d.ts +146 -0
- package/dist/dts/transports/ai-service-error.d.ts.map +1 -0
- package/dist/dts/transports/post-with-retry.d.ts.map +1 -1
- package/dist/dts/types/chat.types.d.ts +72 -11
- package/dist/dts/types/chat.types.d.ts.map +1 -1
- package/dist/esm/index.js +4 -0
- package/dist/esm/transports/ai-service-error.js +183 -0
- package/dist/esm/transports/post-with-retry.js +43 -5
- package/dist/foundation-ai.api.json +756 -37
- package/dist/foundation-ai.d.ts +198 -11
- package/package.json +10 -10
package/dist/foundation-ai.d.ts
CHANGED
|
@@ -64,6 +64,46 @@ export declare interface AggregateUsage {
|
|
|
64
64
|
/** Feature flag name for AI functionality (beta). Enable via ?feature.ai in URL or GENX_ENABLE_AI env var. */
|
|
65
65
|
export declare const AI_FEATURE_FLAG = "ai";
|
|
66
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Refusals that come from the app's gateway, not from its AI service. The Genesis router turns a
|
|
69
|
+
* request away before the service runs: with no session (401) or without the right the endpoint
|
|
70
|
+
* demands (403). Its body is the router's own NACK, with no `code` a proxy would send, so these are
|
|
71
|
+
* kept out of {@link AI_SERVICE_ERROR_CODES}.
|
|
72
|
+
*
|
|
73
|
+
* @beta
|
|
74
|
+
*/
|
|
75
|
+
export declare const AI_SERVICE_ACCESS_REFUSALS: Readonly<{
|
|
76
|
+
/** 401: the request had no session. */
|
|
77
|
+
readonly SIGNED_OUT: "SIGNED_OUT";
|
|
78
|
+
/** 403: the user lacks the right the endpoint demands. */
|
|
79
|
+
readonly ACCESS_DENIED: "ACCESS_DENIED";
|
|
80
|
+
}>;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Every code an AI service may put in an error body. A code not listed here keeps the old,
|
|
84
|
+
* status-based handling: an unknown code must not become a silent dead end, or a retry loop.
|
|
85
|
+
*
|
|
86
|
+
* @beta
|
|
87
|
+
*/
|
|
88
|
+
export declare const AI_SERVICE_ERROR_CODES: Readonly<{
|
|
89
|
+
/** No API key is configured for the vendor. */
|
|
90
|
+
readonly NO_API_KEY: "NO_API_KEY";
|
|
91
|
+
/** The configured key has characters an API key cannot have. */
|
|
92
|
+
readonly BAD_API_KEY: "BAD_API_KEY";
|
|
93
|
+
/** An encrypted key could not be decrypted. */
|
|
94
|
+
readonly KEY_UNREADABLE: "KEY_UNREADABLE";
|
|
95
|
+
/** The request asked for a model the service does not allow. */
|
|
96
|
+
readonly MODEL_NOT_ALLOWED: "MODEL_NOT_ALLOWED";
|
|
97
|
+
/** The service refused the shape of the request. */
|
|
98
|
+
readonly BAD_REQUEST: "BAD_REQUEST";
|
|
99
|
+
/** The request named fallback models, which the service does not accept. */
|
|
100
|
+
readonly FALLBACKS_NOT_SUPPORTED: "FALLBACKS_NOT_SUPPORTED";
|
|
101
|
+
/** The request body is larger, or nested deeper, than the service accepts. */
|
|
102
|
+
readonly REQUEST_TOO_LARGE: "REQUEST_TOO_LARGE";
|
|
103
|
+
/** The service could not reach the vendor. The only code that is worth retrying. */
|
|
104
|
+
readonly VENDOR_UNREACHABLE: "VENDOR_UNREACHABLE";
|
|
105
|
+
}>;
|
|
106
|
+
|
|
67
107
|
/**
|
|
68
108
|
* Every tier id, in ascending capability order.
|
|
69
109
|
*
|
|
@@ -231,6 +271,76 @@ export declare interface AIProviderRegistryStatusEntry {
|
|
|
231
271
|
*/
|
|
232
272
|
export declare type AIProviderType = 'openai' | 'chrome' | 'gemini' | 'anthropic' | 'none';
|
|
233
273
|
|
|
274
|
+
/**
|
|
275
|
+
* One of {@link AI_SERVICE_ACCESS_REFUSALS}.
|
|
276
|
+
*
|
|
277
|
+
* @beta
|
|
278
|
+
*/
|
|
279
|
+
export declare type AIServiceAccessRefusal = (typeof AI_SERVICE_ACCESS_REFUSALS)[keyof typeof AI_SERVICE_ACCESS_REFUSALS];
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* The access refusal behind a 401 or 403 from the app's router, which carries no `code`.
|
|
283
|
+
*
|
|
284
|
+
* Recognised by a positive signal only, like the rest of this module's family: the router's NACK,
|
|
285
|
+
* or an empty body. A vendor's own 401/403, a coded one, and anything else (an HTML page from a
|
|
286
|
+
* proxy in between, say) keep their own handling.
|
|
287
|
+
*
|
|
288
|
+
* @param bodyText - the raw response body, so an empty one can be told from one that isn't JSON.
|
|
289
|
+
* Left out, the body is unknown rather than empty, and only the router's NACK counts.
|
|
290
|
+
* @beta
|
|
291
|
+
*/
|
|
292
|
+
export declare function aiServiceAccessRefusalOf(status: number, payload: unknown, bodyText?: string): AIServiceAccessRefusal | undefined;
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Thrown when the AI service answers with one of {@link AI_SERVICE_ERROR_CODES}, or the app's router
|
|
296
|
+
* refuses the request with one of {@link AI_SERVICE_ACCESS_REFUSALS}.
|
|
297
|
+
*
|
|
298
|
+
* All but `VENDOR_UNREACHABLE` are terminal: sending the same request again gets the same answer
|
|
299
|
+
* until someone changes the configuration, or the user's session or rights.
|
|
300
|
+
*
|
|
301
|
+
* @beta
|
|
302
|
+
*/
|
|
303
|
+
export declare class AIServiceError extends Error {
|
|
304
|
+
/** Vendor label of the transport that was refused (e.g. `'Gemini'`). */
|
|
305
|
+
readonly vendorLabel: string;
|
|
306
|
+
readonly code: AIServiceRefusal;
|
|
307
|
+
/** HTTP status, or the err frame's status on the framed path. */
|
|
308
|
+
readonly status: number;
|
|
309
|
+
/** The service's own message, for the console. Never shown to the user. */
|
|
310
|
+
readonly detail?: string;
|
|
311
|
+
constructor(
|
|
312
|
+
/** Vendor label of the transport that was refused (e.g. `'Gemini'`). */
|
|
313
|
+
vendorLabel: string, code: AIServiceRefusal,
|
|
314
|
+
/** HTTP status, or the err frame's status on the framed path. */
|
|
315
|
+
status: number,
|
|
316
|
+
/** The service's own message, for the console. Never shown to the user. */
|
|
317
|
+
detail?: string);
|
|
318
|
+
/** Whether sending the request again cannot help. */
|
|
319
|
+
get terminal(): boolean;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* One of {@link AI_SERVICE_ERROR_CODES}.
|
|
324
|
+
*
|
|
325
|
+
* @beta
|
|
326
|
+
*/
|
|
327
|
+
export declare type AIServiceErrorCode = (typeof AI_SERVICE_ERROR_CODES)[keyof typeof AI_SERVICE_ERROR_CODES];
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* The code, when it is one of {@link AI_SERVICE_ERROR_CODES}; otherwise `undefined`.
|
|
331
|
+
*
|
|
332
|
+
* @beta
|
|
333
|
+
*/
|
|
334
|
+
export declare function aiServiceErrorCodeOf(code: unknown): AIServiceErrorCode | undefined;
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Everything the chat can tell the user about a refused request: a code the service sent, or an
|
|
338
|
+
* access refusal from in front of it.
|
|
339
|
+
*
|
|
340
|
+
* @beta
|
|
341
|
+
*/
|
|
342
|
+
export declare type AIServiceRefusal = AIServiceErrorCode | AIServiceAccessRefusal;
|
|
343
|
+
|
|
234
344
|
/**
|
|
235
345
|
* AI status for display in the header indicator.
|
|
236
346
|
*
|
|
@@ -2055,6 +2165,8 @@ export declare type ChatToolHandlers<TSubAgent extends {
|
|
|
2055
2165
|
* - `{ ok: false, reason }` — the run ended without completing (see
|
|
2056
2166
|
* {@link SubAgentFailureReason}). The parent handler decides how to
|
|
2057
2167
|
* recover — typically by returning the issue info to its own agent.
|
|
2168
|
+
* With `reason: 'ai_service_error'` it also carries the refusal's `code`
|
|
2169
|
+
* and whether it is `terminal`.
|
|
2058
2170
|
*
|
|
2059
2171
|
* Sub-agents run with tool use forced, so they can no longer end on a
|
|
2060
2172
|
* free-text turn; the previous string fallback has been removed.
|
|
@@ -2063,10 +2175,22 @@ export declare type ChatToolHandlers<TSubAgent extends {
|
|
|
2063
2175
|
ok: true;
|
|
2064
2176
|
result: T;
|
|
2065
2177
|
reason?: never;
|
|
2178
|
+
code?: never;
|
|
2179
|
+
terminal?: never;
|
|
2066
2180
|
} | {
|
|
2067
2181
|
ok: false;
|
|
2068
2182
|
result?: never;
|
|
2069
|
-
reason: SubAgentFailureReason
|
|
2183
|
+
reason: Exclude<SubAgentFailureReason, 'ai_service_error'>;
|
|
2184
|
+
code?: never;
|
|
2185
|
+
terminal?: never;
|
|
2186
|
+
} | {
|
|
2187
|
+
ok: false;
|
|
2188
|
+
result?: never;
|
|
2189
|
+
reason: 'ai_service_error';
|
|
2190
|
+
/** The refusal's code. */
|
|
2191
|
+
code: AIServiceRefusal;
|
|
2192
|
+
/** Whether re-invoking it with the same request gets the same refusal. */
|
|
2193
|
+
terminal: boolean;
|
|
2070
2194
|
}>;
|
|
2071
2195
|
/**
|
|
2072
2196
|
* Signal explicit completion from within a sub-agent tool handler.
|
|
@@ -2113,6 +2237,22 @@ export declare type ChatToolHandlers<TSubAgent extends {
|
|
|
2113
2237
|
* restores the content); non-idempotent tools must use `replaceWith`.
|
|
2114
2238
|
*/
|
|
2115
2239
|
condenseWhen: (policy: CondensePolicy) => void;
|
|
2240
|
+
/**
|
|
2241
|
+
* The current TURN's abort signal: one object for every tool call made while answering
|
|
2242
|
+
* one user message, a new one for the next, and aborted when the user stops the turn or
|
|
2243
|
+
* the view is disposed. One message includes an orchestrated handoff's continuation and a
|
|
2244
|
+
* sub-agent the message delegates to: both see the same object, and a stop reaches both.
|
|
2245
|
+
* A continuation after the user stopped the message is not part of it, and gets a new one.
|
|
2246
|
+
*
|
|
2247
|
+
* Two uses. A long-running handler can listen for it to stop early. And a handler that
|
|
2248
|
+
* must remember something for the rest of the turn — a write the user denied, say — can
|
|
2249
|
+
* key that state on this object (a `WeakMap`), which cannot collide the way a turn number
|
|
2250
|
+
* would when several chat views share one set of handlers.
|
|
2251
|
+
*
|
|
2252
|
+
* Optional: a host that builds its own context may not supply it, and a handler relying on
|
|
2253
|
+
* it must decide what its absence means.
|
|
2254
|
+
*/
|
|
2255
|
+
turnSignal?: AbortSignal;
|
|
2116
2256
|
}) => Promise<unknown>>;
|
|
2117
2257
|
|
|
2118
2258
|
/**
|
|
@@ -2543,6 +2683,15 @@ export declare interface CriteriaInterpretContext {
|
|
|
2543
2683
|
fields?: FieldLike[];
|
|
2544
2684
|
}
|
|
2545
2685
|
|
|
2686
|
+
/**
|
|
2687
|
+
* What the user sees for each code and access refusal. Written for the app's user, with a hint for
|
|
2688
|
+
* whoever runs it, and never quoting the server: its text goes to the console only. A host can
|
|
2689
|
+
* replace any of them (`aiServiceErrorMessages` on the assistant).
|
|
2690
|
+
*
|
|
2691
|
+
* @beta
|
|
2692
|
+
*/
|
|
2693
|
+
export declare const DEFAULT_AI_SERVICE_ERROR_MESSAGES: Readonly<Record<AIServiceRefusal, string>>;
|
|
2694
|
+
|
|
2546
2695
|
/**
|
|
2547
2696
|
* The platform's default tier table.
|
|
2548
2697
|
*
|
|
@@ -2972,6 +3121,13 @@ export declare interface InteractionRequestOptions {
|
|
|
2972
3121
|
* means no timeout — the interaction waits indefinitely.
|
|
2973
3122
|
*/
|
|
2974
3123
|
timeoutMs?: number;
|
|
3124
|
+
/**
|
|
3125
|
+
* Closes the interaction when it aborts, exactly as an unanswered one closes at `timeoutMs`: the
|
|
3126
|
+
* widget goes read-only and `requestInteraction` resolves with `status: 'timeout'`. A tool
|
|
3127
|
+
* handler passes its `turnSignal`, so a user's Stop closes a widget left open instead of leaving
|
|
3128
|
+
* the turn parked on it, and nothing the user clicks afterwards is taken as an answer.
|
|
3129
|
+
*/
|
|
3130
|
+
signal?: AbortSignal;
|
|
2975
3131
|
/**
|
|
2976
3132
|
* How the host frames this widget in the transcript — see
|
|
2977
3133
|
* {@link InteractionPresentation}. Defaults to `'label'` (the historical
|
|
@@ -3079,6 +3235,14 @@ export declare function isObservableAIProviderRegistry(r: AIProviderRegistry): r
|
|
|
3079
3235
|
*/
|
|
3080
3236
|
export declare function isSpeechRecognitionAvailable(): boolean;
|
|
3081
3237
|
|
|
3238
|
+
/**
|
|
3239
|
+
* Whether sending the same request again gets the same refusal. Every code but `VENDOR_UNREACHABLE`
|
|
3240
|
+
* does, until someone changes the configuration or the user's session or rights.
|
|
3241
|
+
*
|
|
3242
|
+
* @beta
|
|
3243
|
+
*/
|
|
3244
|
+
export declare const isTerminalAIServiceRefusal: (code: AIServiceRefusal) => boolean;
|
|
3245
|
+
|
|
3082
3246
|
/**
|
|
3083
3247
|
* Thrown when Gemini returns a `MALFORMED_FUNCTION_CALL` finish reason,
|
|
3084
3248
|
* typically because the model tried to batch multiple tool calls using
|
|
@@ -3542,9 +3706,10 @@ declare interface StructuredPromptOptions {
|
|
|
3542
3706
|
* So a handler that receives it will not be called a second time this turn, and
|
|
3543
3707
|
* the parent turn reports `'budget-exhausted'` in its own right.
|
|
3544
3708
|
*
|
|
3545
|
-
* Recovery guidance differs sharply by reason — see `docs/sub_agent.md`.
|
|
3546
|
-
* `budget_exhausted`
|
|
3547
|
-
*
|
|
3709
|
+
* Recovery guidance differs sharply by reason — see `docs/sub_agent.md`.
|
|
3710
|
+
* `budget_exhausted`, `refusal`, `provider_refused`, `context_exhausted` and a
|
|
3711
|
+
* `terminal` `ai_service_error` are terminal: retrying any of them with the same
|
|
3712
|
+
* request just reproduces it. The rest are worth a retry or a question to the user.
|
|
3548
3713
|
*
|
|
3549
3714
|
* @beta
|
|
3550
3715
|
*/
|
|
@@ -3557,13 +3722,29 @@ export declare type SubAgentFailureReason = 'max_iterations' | 'malformed_tool_c
|
|
|
3557
3722
|
*/
|
|
3558
3723
|
| 'provider_refused'
|
|
3559
3724
|
/**
|
|
3560
|
-
* The sub-agent was stopped because continuing would have overrun the context
|
|
3561
|
-
*
|
|
3562
|
-
*
|
|
3563
|
-
*
|
|
3564
|
-
|
|
3725
|
+
* The sub-agent was stopped because continuing would have overrun the context window
|
|
3726
|
+
* (GENC-1567). Re-invoking it with the same conversation stops it the same way. The parent's turn
|
|
3727
|
+
* goes on, but it shares the conversation whose size caused this, so its own next model call is
|
|
3728
|
+
* likely to stop on the same guard.
|
|
3729
|
+
*/
|
|
3730
|
+
| 'context_exhausted'
|
|
3731
|
+
/**
|
|
3732
|
+
* The app's AI service refused the sub-agent's request (GENC-1611). The outcome carries the
|
|
3733
|
+
* refusal's `code` and whether it is `terminal`: re-invoking the sub-agent with the same request
|
|
3734
|
+
* gets the same refusal, so recover without calling it again. Only a `VENDOR_UNREACHABLE` refusal
|
|
3735
|
+
* is not terminal. Even so, a refusal from your own vendor that is about the service (for example
|
|
3736
|
+
* `VENDOR_UNREACHABLE`) still ends this turn; retry on the user's next message, not in the
|
|
3737
|
+
* handler.
|
|
3738
|
+
*
|
|
3739
|
+
* **Terminal for the PARENT turn too only when** the refusal is about the service rather than the
|
|
3740
|
+
* child's own request (a missing or unusable key, no session or no right, the vendor unreachable)
|
|
3741
|
+
* and the child called the parent's own vendor, unless a completion or a handoff from the same
|
|
3742
|
+
* batch goes on past it. Otherwise the parent is told and its turn goes on. The user is shown a
|
|
3743
|
+
* key, access, model (`MODEL_NOT_ALLOWED`) or reachability refusal's sentence once per user
|
|
3744
|
+
* message; `REQUEST_TOO_LARGE`, `BAD_REQUEST` and `FALLBACKS_NOT_SUPPORTED` are left to the parent
|
|
3745
|
+
* and the console.
|
|
3565
3746
|
*/
|
|
3566
|
-
| '
|
|
3747
|
+
| 'ai_service_error';
|
|
3567
3748
|
|
|
3568
3749
|
/**
|
|
3569
3750
|
* Options passed to `requestSubAgent` at call time.
|
|
@@ -3723,7 +3904,13 @@ export declare type TurnFailureReason = 'exception' | 'malformed-function-call'
|
|
|
3723
3904
|
* the edge rather than issuing a request the provider would reject, so the
|
|
3724
3905
|
* transcript stays intact and compaction is still possible.
|
|
3725
3906
|
*/
|
|
3726
|
-
| 'context-exhausted'
|
|
3907
|
+
| 'context-exhausted'
|
|
3908
|
+
/**
|
|
3909
|
+
* The app's AI service refused the request with one of `AI_SERVICE_ERROR_CODES` (GENC-1611): a
|
|
3910
|
+
* configuration error such as a missing API key, or the vendor still unreachable after the
|
|
3911
|
+
* retries. The transcript says what is wrong in words for the user.
|
|
3912
|
+
*/
|
|
3913
|
+
| 'ai-service-error';
|
|
3727
3914
|
|
|
3728
3915
|
/**
|
|
3729
3916
|
* Display name for each concrete AI vendor: the **single source** every
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genesislcap/foundation-ai",
|
|
3
3
|
"description": "Genesis Foundation AI - Provider-agnostic AI configuration and shared utilities",
|
|
4
|
-
"version": "15.
|
|
4
|
+
"version": "15.41.0",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"license": "SEE LICENSE IN license.txt",
|
|
7
7
|
"main": "dist/esm/index.js",
|
|
@@ -52,17 +52,17 @@
|
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@genesislcap/foundation-testing": "15.
|
|
56
|
-
"@genesislcap/genx": "15.
|
|
57
|
-
"@genesislcap/rollup-builder": "15.
|
|
58
|
-
"@genesislcap/ts-builder": "15.
|
|
59
|
-
"@genesislcap/uvu-playwright-builder": "15.
|
|
60
|
-
"@genesislcap/vite-builder": "15.
|
|
61
|
-
"@genesislcap/webpack-builder": "15.
|
|
55
|
+
"@genesislcap/foundation-testing": "15.41.0",
|
|
56
|
+
"@genesislcap/genx": "15.41.0",
|
|
57
|
+
"@genesislcap/rollup-builder": "15.41.0",
|
|
58
|
+
"@genesislcap/ts-builder": "15.41.0",
|
|
59
|
+
"@genesislcap/uvu-playwright-builder": "15.41.0",
|
|
60
|
+
"@genesislcap/vite-builder": "15.41.0",
|
|
61
|
+
"@genesislcap/webpack-builder": "15.41.0"
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"@genesislcap/foundation-logger": "15.
|
|
65
|
-
"@genesislcap/foundation-utils": "15.
|
|
64
|
+
"@genesislcap/foundation-logger": "15.41.0",
|
|
65
|
+
"@genesislcap/foundation-utils": "15.41.0",
|
|
66
66
|
"@microsoft/fast-foundation": "2.50.0"
|
|
67
67
|
},
|
|
68
68
|
"repository": {
|