@odla-ai/ai 0.1.2 → 0.2.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 +27 -0
- package/dist/index.cjs +102 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +47 -1
- package/dist/index.d.ts +47 -1
- package/dist/index.js +94 -4
- package/dist/index.js.map +1 -1
- package/dist/{openai-Y3OAONAU.js → openai-XZRXMKCC.js} +2 -1
- package/dist/openai-XZRXMKCC.js.map +1 -0
- package/llms.txt +23 -0
- package/package.json +2 -2
- package/dist/openai-Y3OAONAU.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -924,6 +924,38 @@ interface OdlaDbKeyResolverOptions {
|
|
|
924
924
|
* odla-ai throws its own ConfigError) rather than surfacing odla-db's 404. */
|
|
925
925
|
declare function odlaDbKeyResolver(db: OdlaDbClient, opts?: OdlaDbKeyResolverOptions): KeyResolver;
|
|
926
926
|
|
|
927
|
+
interface InitFromPlatformOptions {
|
|
928
|
+
/** Platform base URL (e.g. "https://odla.ai"). */
|
|
929
|
+
platform: string;
|
|
930
|
+
/** The REGISTRY app id — not the env's tenant id. */
|
|
931
|
+
appId: string;
|
|
932
|
+
/** Which environment's config to use ("dev", "prod", …). */
|
|
933
|
+
env: string;
|
|
934
|
+
/** The app's own tenant client — key reads go through `db.secrets.get`. */
|
|
935
|
+
db: OdlaDbClient;
|
|
936
|
+
/** Transport override (tests / non-global fetch). */
|
|
937
|
+
fetch?: typeof fetch;
|
|
938
|
+
/** public-config cache TTL in ms (default 60s; 0 disables caching). */
|
|
939
|
+
ttlMs?: number;
|
|
940
|
+
/** Extra init() options (catalog, injected providers, …). `resolveKey` is
|
|
941
|
+
* owned by this helper; `defaultModel` is used only when the platform
|
|
942
|
+
* config sets no model. */
|
|
943
|
+
initOptions?: Omit<InitOptions, "resolveKey">;
|
|
944
|
+
}
|
|
945
|
+
interface PlatformAi {
|
|
946
|
+
ai: Ai;
|
|
947
|
+
provider: ProviderId;
|
|
948
|
+
model?: string;
|
|
949
|
+
}
|
|
950
|
+
/** Drop all cached platform configs (tests, or to force an immediate refetch). */
|
|
951
|
+
declare function clearPlatformAiCache(): void;
|
|
952
|
+
/** Build an `Ai` from the app's platform registration: provider/model from
|
|
953
|
+
* public-config (cached ~60s), API key from the tenant's odla-db secrets at
|
|
954
|
+
* call time. On cache refresh the existing `Ai` (and its warm key-resolver
|
|
955
|
+
* cache) is reused unless provider/model changed. Note the first call's
|
|
956
|
+
* `db`/`initOptions` are captured for the cache entry's lifetime. */
|
|
957
|
+
declare function initFromPlatform(opts: InitFromPlatformOptions): Promise<PlatformAi>;
|
|
958
|
+
|
|
927
959
|
type FetchLike = typeof fetch;
|
|
928
960
|
interface ProvisionContext {
|
|
929
961
|
/** The odla-db worker URL — always human-supplied, never hardcoded. */
|
|
@@ -946,6 +978,15 @@ declare function pushAgentSchema(ctx: {
|
|
|
946
978
|
}, appId: string, appKey: string): Promise<void>;
|
|
947
979
|
/** Store a named secret (operator/dev token). Value must be a non-`$` string. */
|
|
948
980
|
declare function putSecret(ctx: ProvisionContext, appId: string, name: string, value: string): Promise<void>;
|
|
981
|
+
/** Per-namespace CEL permission rules (odla-db is DEFAULT-DENY: end-users can't
|
|
982
|
+
* read or write any namespace until its rules are set; the app key bypasses
|
|
983
|
+
* rules, so agent-only apps work without them). */
|
|
984
|
+
type AppRules = Record<string, {
|
|
985
|
+
view?: string;
|
|
986
|
+
create?: string;
|
|
987
|
+
update?: string;
|
|
988
|
+
delete?: string;
|
|
989
|
+
}>;
|
|
949
990
|
interface ProvisionAgentAppOptions extends ProvisionContext {
|
|
950
991
|
appId?: string;
|
|
951
992
|
appName?: string;
|
|
@@ -955,6 +996,11 @@ interface ProvisionAgentAppOptions extends ProvisionContext {
|
|
|
955
996
|
secretName?: (provider: ProviderId) => string;
|
|
956
997
|
/** Push the agent schema (default true). */
|
|
957
998
|
pushSchema?: boolean;
|
|
999
|
+
/** Permission rules to install. odla-db is default-deny, so set these for any
|
|
1000
|
+
* namespace end-users should reach (e.g. own-rows-only:
|
|
1001
|
+
* `{ todos: { view: "auth.id == data.ownerId", create: "auth.id == data.ownerId" } }`).
|
|
1002
|
+
* Omit for agent-only apps — the app key bypasses rules. */
|
|
1003
|
+
rules?: AppRules;
|
|
958
1004
|
}
|
|
959
1005
|
interface ProvisionedApp {
|
|
960
1006
|
appId: string;
|
|
@@ -994,4 +1040,4 @@ interface EntityCrudSkillOptions {
|
|
|
994
1040
|
/** Build a CRUD Skill for one odla-db entity. */
|
|
995
1041
|
declare function entityCrudSkill(opts: EntityCrudSkillOptions): Skill;
|
|
996
1042
|
|
|
997
|
-
export { AGENT_SCHEMA, ANTHROPIC_MODELS, type AgentRun, type AgentRunInput, type Ai, type AudioBlock, type AudioMediaType, type AudioSource, AuthError, type Capabilities, CapabilityError, type Catalog, type ChatInput, type ComposedPersona, ConfigError, type ContentBlockDelta, type ContentBlockDeltaEvent, type ContentBlockStartEvent, type ContentBlockStopEvent, ContextWindowError, DEFAULT_CATALOG, DEFAULT_SECRET_NAMES, type DocumentBlock, type DocumentSource, type Effort, type EntityCrudSkillOptions, type EvalCase, type EvalReport, type EvalResult, type EvaluateOptions, type ExtractCall, type ExtractTool, GOOGLE_MODELS, type GradeContext, type GradeResult, type Grader, type ImageBlock, type ImageMediaType, type ImageSource, InMemoryScope, type Inference, type InitOptions, InvalidRequestError, type KeyMap, type KeyOptions, type KeyResolver, type MemoryScope, type MessageDeltaEvent, type MessageStartEvent, type MessageStopEvent, type ModelKind, type ModelSpec, NS, OPENAI_MODELS, OdlaAIError, type OdlaDbClient, type OdlaDbKeyResolverOptions, OdlaDbMemory, type OdlaDbMemoryOptions, type OdlaEntityRef, type OdlaLookup, type OdlaOp, type OdlaQuery, type OdlaScalar, type OracleContentBlock, type OracleErrorEvent, type OracleErrorShape, type OracleErrorType, type OracleEvent, type OracleMessage, type OracleRequest, type OracleResponse, type OracleRole, type OracleStopReason, type OracleTool, type OracleUsage, type PersistRunOptions, type Persona, type Provider, ProviderError, type ProviderFactory, type ProviderId, type ProvisionAgentAppOptions, type ProvisionContext, type ProvisionedApp, type QueryRunsOptions, RateLimitError, type ResponseFormat, type SearchCall, type Skill, type StoppedReason, TaintError, type TaintLabel, type TaintSet, type TextBlock, type ThinkingBlock, type ThinkingMode, type ToolCallRecord, type ToolChoice, type ToolContext, type ToolDef, type ToolHandler, type ToolOutput, type ToolResultBlock, type ToolUseBlock, addUsage, assertSinkAcceptsTaint, blocksOf, buildCatalog, chatCapabilities, clearProviderCache, composeSkills, createApp, emptyUsage, entityCrudSkill, evaluate, exactMatch, extractText, extractToolUses, generateLlmsTxt, getProvider, includes, init, isAudioBlock, isDocumentBlock, isImageBlock, isTextBlock, isThinkingBlock, isToolResultBlock, isToolUseBlock, llmJudge, looksLikeKey, mintAppKey, normalizeError, odlaDbKeyResolver, persistRun, providersInCatalog, provisionAgentApp, pushAgentSchema, putSecret, queryRuns, redact, registerProvider, resolveModel, runAgent, structuredMatch, taint, toOracleTool, validateRequest };
|
|
1043
|
+
export { AGENT_SCHEMA, ANTHROPIC_MODELS, type AgentRun, type AgentRunInput, type Ai, type AudioBlock, type AudioMediaType, type AudioSource, AuthError, type Capabilities, CapabilityError, type Catalog, type ChatInput, type ComposedPersona, ConfigError, type ContentBlockDelta, type ContentBlockDeltaEvent, type ContentBlockStartEvent, type ContentBlockStopEvent, ContextWindowError, DEFAULT_CATALOG, DEFAULT_SECRET_NAMES, type DocumentBlock, type DocumentSource, type Effort, type EntityCrudSkillOptions, type EvalCase, type EvalReport, type EvalResult, type EvaluateOptions, type ExtractCall, type ExtractTool, GOOGLE_MODELS, type GradeContext, type GradeResult, type Grader, type ImageBlock, type ImageMediaType, type ImageSource, InMemoryScope, type Inference, type InitFromPlatformOptions, type InitOptions, InvalidRequestError, type KeyMap, type KeyOptions, type KeyResolver, type MemoryScope, type MessageDeltaEvent, type MessageStartEvent, type MessageStopEvent, type ModelKind, type ModelSpec, NS, OPENAI_MODELS, OdlaAIError, type OdlaDbClient, type OdlaDbKeyResolverOptions, OdlaDbMemory, type OdlaDbMemoryOptions, type OdlaEntityRef, type OdlaLookup, type OdlaOp, type OdlaQuery, type OdlaScalar, type OracleContentBlock, type OracleErrorEvent, type OracleErrorShape, type OracleErrorType, type OracleEvent, type OracleMessage, type OracleRequest, type OracleResponse, type OracleRole, type OracleStopReason, type OracleTool, type OracleUsage, type PersistRunOptions, type Persona, type PlatformAi, type Provider, ProviderError, type ProviderFactory, type ProviderId, type ProvisionAgentAppOptions, type ProvisionContext, type ProvisionedApp, type QueryRunsOptions, RateLimitError, type ResponseFormat, type SearchCall, type Skill, type StoppedReason, TaintError, type TaintLabel, type TaintSet, type TextBlock, type ThinkingBlock, type ThinkingMode, type ToolCallRecord, type ToolChoice, type ToolContext, type ToolDef, type ToolHandler, type ToolOutput, type ToolResultBlock, type ToolUseBlock, addUsage, assertSinkAcceptsTaint, blocksOf, buildCatalog, chatCapabilities, clearPlatformAiCache, clearProviderCache, composeSkills, createApp, emptyUsage, entityCrudSkill, evaluate, exactMatch, extractText, extractToolUses, generateLlmsTxt, getProvider, includes, init, initFromPlatform, isAudioBlock, isDocumentBlock, isImageBlock, isTextBlock, isThinkingBlock, isToolResultBlock, isToolUseBlock, llmJudge, looksLikeKey, mintAppKey, normalizeError, odlaDbKeyResolver, persistRun, providersInCatalog, provisionAgentApp, pushAgentSchema, putSecret, queryRuns, redact, registerProvider, resolveModel, runAgent, structuredMatch, taint, toOracleTool, validateRequest };
|
package/dist/index.d.ts
CHANGED
|
@@ -924,6 +924,38 @@ interface OdlaDbKeyResolverOptions {
|
|
|
924
924
|
* odla-ai throws its own ConfigError) rather than surfacing odla-db's 404. */
|
|
925
925
|
declare function odlaDbKeyResolver(db: OdlaDbClient, opts?: OdlaDbKeyResolverOptions): KeyResolver;
|
|
926
926
|
|
|
927
|
+
interface InitFromPlatformOptions {
|
|
928
|
+
/** Platform base URL (e.g. "https://odla.ai"). */
|
|
929
|
+
platform: string;
|
|
930
|
+
/** The REGISTRY app id — not the env's tenant id. */
|
|
931
|
+
appId: string;
|
|
932
|
+
/** Which environment's config to use ("dev", "prod", …). */
|
|
933
|
+
env: string;
|
|
934
|
+
/** The app's own tenant client — key reads go through `db.secrets.get`. */
|
|
935
|
+
db: OdlaDbClient;
|
|
936
|
+
/** Transport override (tests / non-global fetch). */
|
|
937
|
+
fetch?: typeof fetch;
|
|
938
|
+
/** public-config cache TTL in ms (default 60s; 0 disables caching). */
|
|
939
|
+
ttlMs?: number;
|
|
940
|
+
/** Extra init() options (catalog, injected providers, …). `resolveKey` is
|
|
941
|
+
* owned by this helper; `defaultModel` is used only when the platform
|
|
942
|
+
* config sets no model. */
|
|
943
|
+
initOptions?: Omit<InitOptions, "resolveKey">;
|
|
944
|
+
}
|
|
945
|
+
interface PlatformAi {
|
|
946
|
+
ai: Ai;
|
|
947
|
+
provider: ProviderId;
|
|
948
|
+
model?: string;
|
|
949
|
+
}
|
|
950
|
+
/** Drop all cached platform configs (tests, or to force an immediate refetch). */
|
|
951
|
+
declare function clearPlatformAiCache(): void;
|
|
952
|
+
/** Build an `Ai` from the app's platform registration: provider/model from
|
|
953
|
+
* public-config (cached ~60s), API key from the tenant's odla-db secrets at
|
|
954
|
+
* call time. On cache refresh the existing `Ai` (and its warm key-resolver
|
|
955
|
+
* cache) is reused unless provider/model changed. Note the first call's
|
|
956
|
+
* `db`/`initOptions` are captured for the cache entry's lifetime. */
|
|
957
|
+
declare function initFromPlatform(opts: InitFromPlatformOptions): Promise<PlatformAi>;
|
|
958
|
+
|
|
927
959
|
type FetchLike = typeof fetch;
|
|
928
960
|
interface ProvisionContext {
|
|
929
961
|
/** The odla-db worker URL — always human-supplied, never hardcoded. */
|
|
@@ -946,6 +978,15 @@ declare function pushAgentSchema(ctx: {
|
|
|
946
978
|
}, appId: string, appKey: string): Promise<void>;
|
|
947
979
|
/** Store a named secret (operator/dev token). Value must be a non-`$` string. */
|
|
948
980
|
declare function putSecret(ctx: ProvisionContext, appId: string, name: string, value: string): Promise<void>;
|
|
981
|
+
/** Per-namespace CEL permission rules (odla-db is DEFAULT-DENY: end-users can't
|
|
982
|
+
* read or write any namespace until its rules are set; the app key bypasses
|
|
983
|
+
* rules, so agent-only apps work without them). */
|
|
984
|
+
type AppRules = Record<string, {
|
|
985
|
+
view?: string;
|
|
986
|
+
create?: string;
|
|
987
|
+
update?: string;
|
|
988
|
+
delete?: string;
|
|
989
|
+
}>;
|
|
949
990
|
interface ProvisionAgentAppOptions extends ProvisionContext {
|
|
950
991
|
appId?: string;
|
|
951
992
|
appName?: string;
|
|
@@ -955,6 +996,11 @@ interface ProvisionAgentAppOptions extends ProvisionContext {
|
|
|
955
996
|
secretName?: (provider: ProviderId) => string;
|
|
956
997
|
/** Push the agent schema (default true). */
|
|
957
998
|
pushSchema?: boolean;
|
|
999
|
+
/** Permission rules to install. odla-db is default-deny, so set these for any
|
|
1000
|
+
* namespace end-users should reach (e.g. own-rows-only:
|
|
1001
|
+
* `{ todos: { view: "auth.id == data.ownerId", create: "auth.id == data.ownerId" } }`).
|
|
1002
|
+
* Omit for agent-only apps — the app key bypasses rules. */
|
|
1003
|
+
rules?: AppRules;
|
|
958
1004
|
}
|
|
959
1005
|
interface ProvisionedApp {
|
|
960
1006
|
appId: string;
|
|
@@ -994,4 +1040,4 @@ interface EntityCrudSkillOptions {
|
|
|
994
1040
|
/** Build a CRUD Skill for one odla-db entity. */
|
|
995
1041
|
declare function entityCrudSkill(opts: EntityCrudSkillOptions): Skill;
|
|
996
1042
|
|
|
997
|
-
export { AGENT_SCHEMA, ANTHROPIC_MODELS, type AgentRun, type AgentRunInput, type Ai, type AudioBlock, type AudioMediaType, type AudioSource, AuthError, type Capabilities, CapabilityError, type Catalog, type ChatInput, type ComposedPersona, ConfigError, type ContentBlockDelta, type ContentBlockDeltaEvent, type ContentBlockStartEvent, type ContentBlockStopEvent, ContextWindowError, DEFAULT_CATALOG, DEFAULT_SECRET_NAMES, type DocumentBlock, type DocumentSource, type Effort, type EntityCrudSkillOptions, type EvalCase, type EvalReport, type EvalResult, type EvaluateOptions, type ExtractCall, type ExtractTool, GOOGLE_MODELS, type GradeContext, type GradeResult, type Grader, type ImageBlock, type ImageMediaType, type ImageSource, InMemoryScope, type Inference, type InitOptions, InvalidRequestError, type KeyMap, type KeyOptions, type KeyResolver, type MemoryScope, type MessageDeltaEvent, type MessageStartEvent, type MessageStopEvent, type ModelKind, type ModelSpec, NS, OPENAI_MODELS, OdlaAIError, type OdlaDbClient, type OdlaDbKeyResolverOptions, OdlaDbMemory, type OdlaDbMemoryOptions, type OdlaEntityRef, type OdlaLookup, type OdlaOp, type OdlaQuery, type OdlaScalar, type OracleContentBlock, type OracleErrorEvent, type OracleErrorShape, type OracleErrorType, type OracleEvent, type OracleMessage, type OracleRequest, type OracleResponse, type OracleRole, type OracleStopReason, type OracleTool, type OracleUsage, type PersistRunOptions, type Persona, type Provider, ProviderError, type ProviderFactory, type ProviderId, type ProvisionAgentAppOptions, type ProvisionContext, type ProvisionedApp, type QueryRunsOptions, RateLimitError, type ResponseFormat, type SearchCall, type Skill, type StoppedReason, TaintError, type TaintLabel, type TaintSet, type TextBlock, type ThinkingBlock, type ThinkingMode, type ToolCallRecord, type ToolChoice, type ToolContext, type ToolDef, type ToolHandler, type ToolOutput, type ToolResultBlock, type ToolUseBlock, addUsage, assertSinkAcceptsTaint, blocksOf, buildCatalog, chatCapabilities, clearProviderCache, composeSkills, createApp, emptyUsage, entityCrudSkill, evaluate, exactMatch, extractText, extractToolUses, generateLlmsTxt, getProvider, includes, init, isAudioBlock, isDocumentBlock, isImageBlock, isTextBlock, isThinkingBlock, isToolResultBlock, isToolUseBlock, llmJudge, looksLikeKey, mintAppKey, normalizeError, odlaDbKeyResolver, persistRun, providersInCatalog, provisionAgentApp, pushAgentSchema, putSecret, queryRuns, redact, registerProvider, resolveModel, runAgent, structuredMatch, taint, toOracleTool, validateRequest };
|
|
1043
|
+
export { AGENT_SCHEMA, ANTHROPIC_MODELS, type AgentRun, type AgentRunInput, type Ai, type AudioBlock, type AudioMediaType, type AudioSource, AuthError, type Capabilities, CapabilityError, type Catalog, type ChatInput, type ComposedPersona, ConfigError, type ContentBlockDelta, type ContentBlockDeltaEvent, type ContentBlockStartEvent, type ContentBlockStopEvent, ContextWindowError, DEFAULT_CATALOG, DEFAULT_SECRET_NAMES, type DocumentBlock, type DocumentSource, type Effort, type EntityCrudSkillOptions, type EvalCase, type EvalReport, type EvalResult, type EvaluateOptions, type ExtractCall, type ExtractTool, GOOGLE_MODELS, type GradeContext, type GradeResult, type Grader, type ImageBlock, type ImageMediaType, type ImageSource, InMemoryScope, type Inference, type InitFromPlatformOptions, type InitOptions, InvalidRequestError, type KeyMap, type KeyOptions, type KeyResolver, type MemoryScope, type MessageDeltaEvent, type MessageStartEvent, type MessageStopEvent, type ModelKind, type ModelSpec, NS, OPENAI_MODELS, OdlaAIError, type OdlaDbClient, type OdlaDbKeyResolverOptions, OdlaDbMemory, type OdlaDbMemoryOptions, type OdlaEntityRef, type OdlaLookup, type OdlaOp, type OdlaQuery, type OdlaScalar, type OracleContentBlock, type OracleErrorEvent, type OracleErrorShape, type OracleErrorType, type OracleEvent, type OracleMessage, type OracleRequest, type OracleResponse, type OracleRole, type OracleStopReason, type OracleTool, type OracleUsage, type PersistRunOptions, type Persona, type PlatformAi, type Provider, ProviderError, type ProviderFactory, type ProviderId, type ProvisionAgentAppOptions, type ProvisionContext, type ProvisionedApp, type QueryRunsOptions, RateLimitError, type ResponseFormat, type SearchCall, type Skill, type StoppedReason, TaintError, type TaintLabel, type TaintSet, type TextBlock, type ThinkingBlock, type ThinkingMode, type ToolCallRecord, type ToolChoice, type ToolContext, type ToolDef, type ToolHandler, type ToolOutput, type ToolResultBlock, type ToolUseBlock, addUsage, assertSinkAcceptsTaint, blocksOf, buildCatalog, chatCapabilities, clearPlatformAiCache, clearProviderCache, composeSkills, createApp, emptyUsage, entityCrudSkill, evaluate, exactMatch, extractText, extractToolUses, generateLlmsTxt, getProvider, includes, init, initFromPlatform, isAudioBlock, isDocumentBlock, isImageBlock, isTextBlock, isThinkingBlock, isToolResultBlock, isToolUseBlock, llmJudge, looksLikeKey, mintAppKey, normalizeError, odlaDbKeyResolver, persistRun, providersInCatalog, provisionAgentApp, pushAgentSchema, putSecret, queryRuns, redact, registerProvider, resolveModel, runAgent, structuredMatch, taint, toOracleTool, validateRequest };
|
package/dist/index.js
CHANGED
|
@@ -139,6 +139,22 @@ var OPENAI_MODELS = [
|
|
|
139
139
|
capabilities: chatCapabilities({ effort: true }),
|
|
140
140
|
contextWindow: 4e5
|
|
141
141
|
},
|
|
142
|
+
{
|
|
143
|
+
id: "gpt-5-nano",
|
|
144
|
+
provider: "openai",
|
|
145
|
+
nativeId: "gpt-5-nano",
|
|
146
|
+
capabilities: chatCapabilities({ effort: true }),
|
|
147
|
+
contextWindow: 4e5
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
// Search-tuned chat model: the adapter sends web_search_options when a
|
|
151
|
+
// request sets webSearch. No reasoning-effort knob.
|
|
152
|
+
id: "gpt-5-search-api",
|
|
153
|
+
provider: "openai",
|
|
154
|
+
nativeId: "gpt-5-search-api",
|
|
155
|
+
capabilities: chatCapabilities({ webSearch: true }),
|
|
156
|
+
contextWindow: 4e5
|
|
157
|
+
},
|
|
142
158
|
{
|
|
143
159
|
// Non-reasoning multimodal chat (image input, no effort knob).
|
|
144
160
|
id: "gpt-4o",
|
|
@@ -239,7 +255,7 @@ async function getProvider(id, apiKey) {
|
|
|
239
255
|
break;
|
|
240
256
|
}
|
|
241
257
|
case "openai": {
|
|
242
|
-
const { OpenAIProvider } = await import("./openai-
|
|
258
|
+
const { OpenAIProvider } = await import("./openai-XZRXMKCC.js");
|
|
243
259
|
provider = new OpenAIProvider(apiKey);
|
|
244
260
|
break;
|
|
245
261
|
}
|
|
@@ -456,6 +472,27 @@ Secrets are read-only from the app key (odlaDbKeyResolver \u2192 db.secrets.get)
|
|
|
456
472
|
are WRITTEN only with the operator/dev token via provisionAgentApp/putSecret. Keys
|
|
457
473
|
are AES-GCM-encrypted at rest in odla-db and never returned to browser clients.
|
|
458
474
|
|
|
475
|
+
## Platform wiring (odla.ai apps registry)
|
|
476
|
+
|
|
477
|
+
Apps registered on the odla platform get LLM access as an APP SETTING \u2014
|
|
478
|
+
never put provider keys in your Worker's wrangler vars/secrets. Provider +
|
|
479
|
+
default model are per-environment registry config (set in Studio's AI card
|
|
480
|
+
or \`@odla-ai/apps\` setAi); the API key lives in the platform vault (the
|
|
481
|
+
env's odla-db tenant secrets, write-only for operators). One call reads both:
|
|
482
|
+
|
|
483
|
+
import { initFromPlatform } from "@odla-ai/ai";
|
|
484
|
+
import { init as odlaInit } from "@odla-ai/db";
|
|
485
|
+
|
|
486
|
+
const db = odlaInit({ appId: TENANT, adminToken: env.ODLA_API_KEY, endpoint: "https://db.odla.ai" });
|
|
487
|
+
const { ai, provider, model } = await initFromPlatform({
|
|
488
|
+
platform: "https://odla.ai", appId: APP_ID, env: "prod", db });
|
|
489
|
+
// ai.chat / ai.stream / ai.extract \u2014 provider/model from public-config
|
|
490
|
+
// (cached ~60s, so Studio changes apply without redeploys); the key is
|
|
491
|
+
// fetched from the vault at call time via odlaDbKeyResolver.
|
|
492
|
+
|
|
493
|
+
The only secret the Worker carries is its odla-db app key. Rotating the LLM
|
|
494
|
+
key = writing the secret again; switching provider/model = a Studio edit.
|
|
495
|
+
|
|
459
496
|
## Errors
|
|
460
497
|
|
|
461
498
|
Every error is an OdlaAIError subclass with a stable \`code\` \u2014 branch on err.code:
|
|
@@ -883,15 +920,15 @@ var DEFAULT_SECRET_NAMES = {
|
|
|
883
920
|
function odlaDbKeyResolver(db, opts = {}) {
|
|
884
921
|
const nameFor = opts.secretName ?? ((p) => DEFAULT_SECRET_NAMES[p]);
|
|
885
922
|
const useCache = opts.cache ?? true;
|
|
886
|
-
const
|
|
923
|
+
const cache3 = /* @__PURE__ */ new Map();
|
|
887
924
|
return async (provider) => {
|
|
888
925
|
if (useCache) {
|
|
889
|
-
const hit =
|
|
926
|
+
const hit = cache3.get(provider);
|
|
890
927
|
if (hit !== void 0) return hit;
|
|
891
928
|
}
|
|
892
929
|
try {
|
|
893
930
|
const key = await db.secrets.get(nameFor(provider));
|
|
894
|
-
if (useCache)
|
|
931
|
+
if (useCache) cache3.set(provider, key);
|
|
895
932
|
return key;
|
|
896
933
|
} catch {
|
|
897
934
|
return void 0;
|
|
@@ -899,6 +936,51 @@ function odlaDbKeyResolver(db, opts = {}) {
|
|
|
899
936
|
};
|
|
900
937
|
}
|
|
901
938
|
|
|
939
|
+
// src/store/platform.ts
|
|
940
|
+
var cache2 = /* @__PURE__ */ new Map();
|
|
941
|
+
function clearPlatformAiCache() {
|
|
942
|
+
cache2.clear();
|
|
943
|
+
}
|
|
944
|
+
async function fetchAiConfig(opts) {
|
|
945
|
+
const doFetch = opts.fetch ?? fetch;
|
|
946
|
+
const base = opts.platform.replace(/\/$/, "");
|
|
947
|
+
const url = `${base}/registry/apps/${encodeURIComponent(opts.appId)}/public-config?env=${encodeURIComponent(opts.env)}`;
|
|
948
|
+
const res = await doFetch(url);
|
|
949
|
+
if (!res.ok) throw new ProviderError(`platform public-config fetch failed: ${res.status} for ${opts.appId}/${opts.env}`);
|
|
950
|
+
const cfg = await res.json();
|
|
951
|
+
const ai = cfg.ai;
|
|
952
|
+
if (!ai || typeof ai.provider !== "string") {
|
|
953
|
+
throw new ConfigError(
|
|
954
|
+
`ai service is not enabled/configured for "${opts.appId}" (${opts.env}) \u2014 enable it in Studio or via @odla-ai/apps setAi(appId, env, { provider }).`
|
|
955
|
+
);
|
|
956
|
+
}
|
|
957
|
+
if (!(ai.provider in DEFAULT_SECRET_NAMES)) {
|
|
958
|
+
throw new ConfigError(`platform ai config names unknown provider "${ai.provider}" for "${opts.appId}" (${opts.env}).`);
|
|
959
|
+
}
|
|
960
|
+
const model = typeof ai.model === "string" && ai.model ? ai.model : void 0;
|
|
961
|
+
return { provider: ai.provider, ...model ? { model } : {} };
|
|
962
|
+
}
|
|
963
|
+
async function initFromPlatform(opts) {
|
|
964
|
+
const ttl = opts.ttlMs ?? 6e4;
|
|
965
|
+
const key = `${opts.platform}|${opts.appId}|${opts.env}`;
|
|
966
|
+
const now = Date.now();
|
|
967
|
+
const hit = ttl > 0 ? cache2.get(key) : void 0;
|
|
968
|
+
if (hit && hit.expiresAt > now) return hit.value;
|
|
969
|
+
const { provider, model } = await fetchAiConfig(opts);
|
|
970
|
+
if (hit && hit.value.provider === provider && hit.value.model === model) {
|
|
971
|
+
hit.expiresAt = now + ttl;
|
|
972
|
+
return hit.value;
|
|
973
|
+
}
|
|
974
|
+
const ai = init({
|
|
975
|
+
...opts.initOptions,
|
|
976
|
+
resolveKey: odlaDbKeyResolver(opts.db),
|
|
977
|
+
defaultModel: model ?? opts.initOptions?.defaultModel
|
|
978
|
+
});
|
|
979
|
+
const value = { ai, provider, ...model ? { model } : {} };
|
|
980
|
+
if (ttl > 0) cache2.set(key, { value, expiresAt: now + ttl });
|
|
981
|
+
return value;
|
|
982
|
+
}
|
|
983
|
+
|
|
902
984
|
// src/store/provision.ts
|
|
903
985
|
async function post(ctx, path, body) {
|
|
904
986
|
const f = ctx.fetch ?? fetch;
|
|
@@ -941,6 +1023,9 @@ async function pushAgentSchema(ctx, appId, appKey) {
|
|
|
941
1023
|
async function putSecret(ctx, appId, name, value) {
|
|
942
1024
|
await post(ctx, `/admin/apps/${encodeURIComponent(appId)}/secrets`, { name, value });
|
|
943
1025
|
}
|
|
1026
|
+
async function putRules(ctx, appId, rules) {
|
|
1027
|
+
await post(ctx, `/app/${encodeURIComponent(appId)}/admin/rules`, rules);
|
|
1028
|
+
}
|
|
944
1029
|
async function provisionAgentApp(opts) {
|
|
945
1030
|
const ctx = { endpoint: opts.endpoint, token: opts.token, fetch: opts.fetch };
|
|
946
1031
|
const appId = await createApp(ctx, { appId: opts.appId, name: opts.appName });
|
|
@@ -948,6 +1033,9 @@ async function provisionAgentApp(opts) {
|
|
|
948
1033
|
if (opts.pushSchema !== false) {
|
|
949
1034
|
await pushAgentSchema({ endpoint: opts.endpoint, fetch: opts.fetch }, appId, appKey);
|
|
950
1035
|
}
|
|
1036
|
+
if (opts.rules) {
|
|
1037
|
+
await putRules(ctx, appId, opts.rules);
|
|
1038
|
+
}
|
|
951
1039
|
const nameFor = opts.secretName ?? ((p) => DEFAULT_SECRET_NAMES[p]);
|
|
952
1040
|
for (const [provider, value] of Object.entries(opts.providerKeys ?? {})) {
|
|
953
1041
|
if (!value) continue;
|
|
@@ -1102,6 +1190,7 @@ export {
|
|
|
1102
1190
|
blocksOf,
|
|
1103
1191
|
buildCatalog,
|
|
1104
1192
|
chatCapabilities,
|
|
1193
|
+
clearPlatformAiCache,
|
|
1105
1194
|
clearProviderCache,
|
|
1106
1195
|
composeSkills,
|
|
1107
1196
|
createApp,
|
|
@@ -1115,6 +1204,7 @@ export {
|
|
|
1115
1204
|
getProvider,
|
|
1116
1205
|
includes,
|
|
1117
1206
|
init,
|
|
1207
|
+
initFromPlatform,
|
|
1118
1208
|
isAudioBlock,
|
|
1119
1209
|
isDocumentBlock,
|
|
1120
1210
|
isImageBlock,
|