@theokit/agents 4.7.0 → 4.9.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/auth.d.ts CHANGED
@@ -31,6 +31,16 @@ declare class AuthProvider {
31
31
  * thread through. Returns the fresh `ResolvedCredential` — never logs the rotated token.
32
32
  */
33
33
  ensureFresh(resolved: ResolvedCredential, deps: EnsureFreshHttpDeps, env?: Record<string, string | undefined>): Promise<ResolvedCredential>;
34
+ /** Refresh em voo por caminho de store — a chave é o arquivo, não a instância. */
35
+ private static readonly refreshEmVoo;
36
+ /**
37
+ * O refresh propriamente dito, serializado entre PROCESSOS e com re-leitura.
38
+ *
39
+ * A re-leitura não é detalhe: sem ela o lock apenas serializa, e o segundo processo decide com o
40
+ * estado que leu ANTES de esperar — refrescando de novo e invalidando o token que o primeiro acabou
41
+ * de gravar. É o double-checked locking clássico, e é o que o teste de dois processos pega.
42
+ */
43
+ private refrescarSobLock;
34
44
  /**
35
45
  * Run the headless OpenAI device-login flow. Delegates to `openaiDeviceLogin` (which JWT-extracts the
36
46
  * account id). `deviceConfig` is passed per-call because it is a distinct endpoint set from the
package/dist/auth.js CHANGED
@@ -3,8 +3,9 @@ import {
3
3
  } from "./chunk-7QVYU63E.js";
4
4
 
5
5
  // src/auth/auth-provider.ts
6
- import { ensureFreshCredential, openaiDeviceLogin, persistOAuthTokens } from "@theokit/sdk/auth";
7
- var AuthProvider = class {
6
+ import { authFilePath, ensureFreshCredential, openaiDeviceLogin, persistOAuthTokens, readStoredOAuth } from "@theokit/sdk/auth";
7
+ import { withFileLock } from "@theokit/sdk/persistence";
8
+ var AuthProvider = class _AuthProvider {
8
9
  static {
9
10
  __name(this, "AuthProvider");
10
11
  }
@@ -19,12 +20,48 @@ var AuthProvider = class {
19
20
  * `config` + `store`; `env` (for reading the store's env overrides) + the `{ fetch, now }` HTTP deps
20
21
  * thread through. Returns the fresh `ResolvedCredential` — never logs the rotated token.
21
22
  */
22
- ensureFresh(resolved, deps, env) {
23
- return ensureFreshCredential(resolved, {
24
- config: this.config,
25
- store: this.store,
26
- env
27
- }, deps);
23
+ async ensureFresh(resolved, deps, env) {
24
+ if (resolved.kind !== "oauth") {
25
+ return ensureFreshCredential(resolved, {
26
+ config: this.config,
27
+ store: this.store,
28
+ env
29
+ }, deps);
30
+ }
31
+ const caminho = authFilePath(this.store, env);
32
+ const emVoo = _AuthProvider.refreshEmVoo.get(caminho);
33
+ if (emVoo !== void 0) return emVoo;
34
+ const promessa = this.refrescarSobLock(caminho, resolved, deps, env);
35
+ _AuthProvider.refreshEmVoo.set(caminho, promessa);
36
+ try {
37
+ return await promessa;
38
+ } finally {
39
+ _AuthProvider.refreshEmVoo.delete(caminho);
40
+ }
41
+ }
42
+ /** Refresh em voo por caminho de store — a chave é o arquivo, não a instância. */
43
+ static refreshEmVoo = /* @__PURE__ */ new Map();
44
+ /**
45
+ * O refresh propriamente dito, serializado entre PROCESSOS e com re-leitura.
46
+ *
47
+ * A re-leitura não é detalhe: sem ela o lock apenas serializa, e o segundo processo decide com o
48
+ * estado que leu ANTES de esperar — refrescando de novo e invalidando o token que o primeiro acabou
49
+ * de gravar. É o double-checked locking clássico, e é o que o teste de dois processos pega.
50
+ */
51
+ refrescarSobLock(caminho, resolved, deps, env) {
52
+ return withFileLock(caminho, async () => {
53
+ const doDisco = readStoredOAuth(this.store, env);
54
+ const atual = doDisco !== void 0 ? {
55
+ ...resolved,
56
+ apiKey: doDisco.access,
57
+ expiresAt: doDisco.expires
58
+ } : resolved;
59
+ return await ensureFreshCredential(atual, {
60
+ config: this.config,
61
+ store: this.store,
62
+ env
63
+ }, deps);
64
+ });
28
65
  }
29
66
  /**
30
67
  * Run the headless OpenAI device-login flow. Delegates to `openaiDeviceLogin` (which JWT-extracts the
@@ -44,14 +81,14 @@ var AuthProvider = class {
44
81
  };
45
82
 
46
83
  // src/auth-entry.ts
47
- import { authFilePath, CredentialError, credentialHome, readAuthFile, readStoredOAuth, writeCredential } from "@theokit/sdk/auth";
84
+ import { authFilePath as authFilePath2, CredentialError, credentialHome, readAuthFile, readStoredOAuth as readStoredOAuth2, writeCredential } from "@theokit/sdk/auth";
48
85
  export {
49
86
  AuthProvider,
50
87
  CredentialError,
51
- authFilePath,
88
+ authFilePath2 as authFilePath,
52
89
  credentialHome,
53
90
  readAuthFile,
54
- readStoredOAuth,
91
+ readStoredOAuth2 as readStoredOAuth,
55
92
  writeCredential
56
93
  };
57
94
  //# sourceMappingURL=auth.js.map
package/dist/auth.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/auth/auth-provider.ts","../src/auth-entry.ts"],"sourcesContent":["import { ensureFreshCredential, openaiDeviceLogin, persistOAuthTokens } from '@theokit/sdk/auth'\nimport type {\n CredentialStoreConfig,\n OAuthProviderConfig,\n OAuthTokens,\n OpenAIDeviceConfig,\n ResolvedCredential,\n} from '@theokit/sdk/auth'\n\n/**\n * M60 — `AuthProvider`, the OO contract that unifies the SDK's free OAuth-lifecycle functions\n * (`openaiDeviceLogin` → `persistOAuthTokens` → `ensureFreshCredential`). Those are stateful across a\n * SHARED `config` (`OAuthProviderConfig`) + `store` (`CredentialStoreConfig`); this class holds that\n * state so a consumer authors `new AuthProvider(config, store).persist(...)` / `.ensureFresh(...)`\n * instead of threading `config`/`store` through every call — the `SDK → Theokit → AgentBuilder`\n * boundary applied to the auth domain (ENRICH, per blueprint D2: auth carries orchestration + state).\n *\n * It DELEGATES, never reimplements (parsimony Rung 9): each method forwards verbatim to the SDK\n * function, so login → persist → refresh produces byte-identical state to calling the SDK directly.\n *\n * SECRET-SAFETY (hard rule): this class NEVER logs, stringifies, or otherwise surfaces token material.\n * Methods return exactly what the SDK returns and add no observability — a token is data that flows\n * through, never something this layer emits. The parity/secret tests pin both properties.\n */\n\n/** The HTTP deps of `ensureFreshCredential` (`{ fetch, now }`) — typed off the SDK to avoid drift. */\ntype EnsureFreshHttpDeps = Parameters<typeof ensureFreshCredential>[2]\n/** The device-flow deps + prompt hook of `openaiDeviceLogin` — typed off the SDK. */\ntype DeviceLoginDeps = Parameters<typeof openaiDeviceLogin>[1]\ntype DeviceLoginHooks = Parameters<typeof openaiDeviceLogin>[2]\n\nexport class AuthProvider {\n constructor(\n private readonly config: OAuthProviderConfig,\n private readonly store: CredentialStoreConfig,\n ) {}\n\n /**\n * Refresh a resolved credential if stale. Delegates to `ensureFreshCredential` with the held\n * `config` + `store`; `env` (for reading the store's env overrides) + the `{ fetch, now }` HTTP deps\n * thread through. Returns the fresh `ResolvedCredential` — never logs the rotated token.\n */\n ensureFresh(\n resolved: ResolvedCredential,\n deps: EnsureFreshHttpDeps,\n env?: Record<string, string | undefined>,\n ): Promise<ResolvedCredential> {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- `CredentialStoreConfig` (SDK `/auth` subpath) resolves under tsc (root typecheck is clean) but eslint's type-aware project reads `this.store` as error-typed; the assignment is type-safe per tsc.\n return ensureFreshCredential(resolved, { config: this.config, store: this.store, env }, deps)\n }\n\n /**\n * Run the headless OpenAI device-login flow. Delegates to `openaiDeviceLogin` (which JWT-extracts the\n * account id). `deviceConfig` is passed per-call because it is a distinct endpoint set from the\n * refresh `config`. Returns `OAuthTokens` — the caller persists them via {@link AuthProvider.persist}.\n */\n deviceLogin(\n deviceConfig: OpenAIDeviceConfig,\n deps: DeviceLoginDeps,\n hooks: DeviceLoginHooks,\n ): Promise<OAuthTokens> {\n return openaiDeviceLogin(deviceConfig, deps, hooks)\n }\n\n /**\n * Persist freshly-obtained tokens through the held `store`. Delegates to `persistOAuthTokens` and\n * returns the credential-file path (never the token). `env` selects the store's home override.\n */\n persist(provider: string, tokens: OAuthTokens, env?: Record<string, string | undefined>): string {\n return persistOAuthTokens(provider, tokens, this.store, env)\n }\n}\n","// M60 — `@theokit/agents/auth`: the OO auth contract. `AuthProvider` (ENRICH — it holds the shared\n// `config`+`store` state and delegates to the SDK's free OAuth-lifecycle functions), plus the auth\n// domain's types re-exported so a consumer types the whole surface from the Theokit layer, never\n// reaching back to `@theokit/sdk/auth`.\nexport { AuthProvider } from './auth/auth-provider.js'\n\n// M73 — \"enriquecer nunca reduz\". A mecânica de store do SDK atravessa como PASS-THROUGH PURO.\n//\n// Antes disto, este subpath exportava 1 valor e 6 tipos enquanto `@theokit/sdk/auth` exportava 19\n// símbolos: nenhuma função atravessava. Como o consumidor tem regra INQUEBRÁVEL de nunca importar\n// `@theokit/sdk*` direto, **reimplementar era a única saída legal** — e o agent-builder reescreveu\n// seis destes nomes, ~120 linhas de mecânica duplicada. A lacuna era daqui, não indisciplina de lá.\n//\n// PURO, e não wrapper (parsimony Rung 9): estas são funções de I/O sem estado a segurar. A camada\n// enriquece onde há orquestração — é o que `AuthProvider` faz com o par `config`+`store`. Envolver\n// isto acrescentaria indireção sem nada dentro, e **quebraria `instanceof`**: o consumidor faz\n// `err instanceof CredentialError`, o que só vale enquanto a classe for a MESMA referência do SDK.\n// `tests/unit/auth-parity.test.ts` trava essa identidade com `toBe`.\n//\n// `resolveCredential` NÃO atravessa, de propósito: o SDK e o agent-builder têm funções DIFERENTES com\n// esse nome (sync vs async, lança vs `undefined`, lê env vs não lê, infere provider vs recusa), e o\n// próprio SDK declara que a precedência de env, a inferência por prefixo e o provider declarado são\n// app policy do consumidor (`internal/auth/credential-store.ts`). Expor os dois no mesmo escopo seria\n// convite a importar o errado, com falha silenciosa.\nexport {\n authFilePath,\n CredentialError,\n credentialHome,\n readAuthFile,\n readStoredOAuth,\n writeCredential,\n} from '@theokit/sdk/auth'\nexport type { ResolveCredentialOptions } from '@theokit/sdk/auth'\nexport type {\n CredentialStoreConfig,\n DeviceDeps,\n OAuthProviderConfig,\n OAuthTokens,\n OpenAIDeviceConfig,\n ResolvedCredential,\n} from '@theokit/sdk/auth'\n"],"mappings":";;;;;AAAA,SAASA,uBAAuBC,mBAAmBC,0BAA0B;AA+BtE,IAAMC,eAAN,MAAMA;EA/Bb,OA+BaA;;;;;EACX,YACmBC,QACAC,OACjB;SAFiBD,SAAAA;SACAC,QAAAA;EAChB;;;;;;EAOHC,YACEC,UACAC,MACAC,KAC6B;AAE7B,WAAOC,sBAAsBH,UAAU;MAAEH,QAAQ,KAAKA;MAAQC,OAAO,KAAKA;MAAOI;IAAI,GAAGD,IAAAA;EAC1F;;;;;;EAOAG,YACEC,cACAJ,MACAK,OACsB;AACtB,WAAOC,kBAAkBF,cAAcJ,MAAMK,KAAAA;EAC/C;;;;;EAMAE,QAAQC,UAAkBC,QAAqBR,KAAkD;AAC/F,WAAOS,mBAAmBF,UAAUC,QAAQ,KAAKZ,OAAOI,GAAAA;EAC1D;AACF;;;AC/CA,SACEU,cACAC,iBACAC,gBACAC,cACAC,iBACAC,uBACK;","names":["ensureFreshCredential","openaiDeviceLogin","persistOAuthTokens","AuthProvider","config","store","ensureFresh","resolved","deps","env","ensureFreshCredential","deviceLogin","deviceConfig","hooks","openaiDeviceLogin","persist","provider","tokens","persistOAuthTokens","authFilePath","CredentialError","credentialHome","readAuthFile","readStoredOAuth","writeCredential"]}
1
+ {"version":3,"sources":["../src/auth/auth-provider.ts","../src/auth-entry.ts"],"sourcesContent":["import {\n authFilePath,\n ensureFreshCredential,\n openaiDeviceLogin,\n persistOAuthTokens,\n readStoredOAuth,\n} from '@theokit/sdk/auth'\nimport type {\n CredentialStoreConfig,\n OAuthProviderConfig,\n OAuthTokens,\n OpenAIDeviceConfig,\n ResolvedCredential,\n} from '@theokit/sdk/auth'\nimport { withFileLock } from '@theokit/sdk/persistence'\n\n/**\n * M60 — `AuthProvider`, the OO contract that unifies the SDK's free OAuth-lifecycle functions\n * (`openaiDeviceLogin` → `persistOAuthTokens` → `ensureFreshCredential`). Those are stateful across a\n * SHARED `config` (`OAuthProviderConfig`) + `store` (`CredentialStoreConfig`); this class holds that\n * state so a consumer authors `new AuthProvider(config, store).persist(...)` / `.ensureFresh(...)`\n * instead of threading `config`/`store` through every call — the `SDK → Theokit → AgentBuilder`\n * boundary applied to the auth domain (ENRICH, per blueprint D2: auth carries orchestration + state).\n *\n * It DELEGATES, never reimplements (parsimony Rung 9): each method forwards verbatim to the SDK\n * function, so login → persist → refresh produces byte-identical state to calling the SDK directly.\n *\n * SECRET-SAFETY (hard rule): this class NEVER logs, stringifies, or otherwise surfaces token material.\n * Methods return exactly what the SDK returns and add no observability — a token is data that flows\n * through, never something this layer emits. The parity/secret tests pin both properties.\n */\n\n/** The HTTP deps of `ensureFreshCredential` (`{ fetch, now }`) — typed off the SDK to avoid drift. */\ntype EnsureFreshHttpDeps = Parameters<typeof ensureFreshCredential>[2]\n/** The device-flow deps + prompt hook of `openaiDeviceLogin` — typed off the SDK. */\ntype DeviceLoginDeps = Parameters<typeof openaiDeviceLogin>[1]\ntype DeviceLoginHooks = Parameters<typeof openaiDeviceLogin>[2]\n\n/**\n * Falha de refresh, classificada — porque a decisão de tentar de novo depende da classe, não do texto.\n *\n * M74: repetir um `invalid_grant` não é resiliência, é ruído. O refresh token foi revogado e nenhuma\n * tentativa muda isso; o usuário que revogou o login espera três backoffs para ler uma mensagem que já\n * era conhecida na primeira resposta. Rede e 5xx são o oposto: quase sempre passam na segunda.\n *\n * SECRET-SAFETY: a mensagem nunca carrega material de token — só a classe e o motivo.\n */\nexport class RefreshFailure extends Error {\n constructor(\n message: string,\n /** `true` ⇒ vale tentar de novo com backoff. `false` ⇒ terminal, falha na primeira. */\n readonly transitorio: boolean,\n ) {\n super(message)\n this.name = 'RefreshFailure'\n }\n}\n\n/**\n * O que conta como transitório. Lista NOMEADA de propósito: é decisão de produto que envelhece, e\n * espalhá-la em `if` faz cada sítio envelhecer sozinho.\n */\nconst MOTIVOS_TRANSITORIOS = [\n 'ETIMEDOUT',\n 'ECONNRESET',\n 'ECONNREFUSED',\n 'EAI_AGAIN',\n 'ENOTFOUND',\n 'AbortError',\n]\n\n/** Classifica uma falha de refresh. `invalid_grant` é terminal; rede e 5xx são transitórios. */\nexport function classificarFalhaDeRefresh(err: unknown): RefreshFailure {\n const texto = err instanceof Error ? `${err.name}: ${err.message}` : String(err)\n if (/invalid_grant|invalid_request|unauthorized_client/i.test(texto)) {\n return new RefreshFailure(\n 'o refresh token não é mais válido — refaça o login. Tentar de novo não muda o resultado.',\n false,\n )\n }\n const transitorio =\n MOTIVOS_TRANSITORIOS.some((m) => texto.includes(m)) ||\n /\\b(5\\d{2})\\b|timeout|network/i.test(texto)\n return new RefreshFailure(\n transitorio ? 'falha transitória ao refrescar a credencial' : 'falha ao refrescar a credencial',\n transitorio,\n )\n}\n\n/** Espera com jitter: backoff exponencial ±25%, para dois processos não retentarem em uníssono. */\nexport function esperaComJitter(tentativa: number, baseMs = 200, aleatorio = Math.random): number {\n const base = baseMs * 2 ** tentativa\n return Math.round(base * (0.75 + aleatorio() * 0.5))\n}\n\nexport class AuthProvider {\n constructor(\n private readonly config: OAuthProviderConfig,\n private readonly store: CredentialStoreConfig,\n ) {}\n\n /**\n * Refresh a resolved credential if stale. Delegates to `ensureFreshCredential` with the held\n * `config` + `store`; `env` (for reading the store's env overrides) + the `{ fetch, now }` HTTP deps\n * thread through. Returns the fresh `ResolvedCredential` — never logs the rotated token.\n */\n async ensureFresh(\n resolved: ResolvedCredential,\n deps: EnsureFreshHttpDeps,\n env?: Record<string, string | undefined>,\n ): Promise<ResolvedCredential> {\n if (resolved.kind !== 'oauth') {\n // Chave de API não expira: nenhum lock, nenhuma releitura, nenhum I/O. Manter o caminho quente\n // livre é o que torna o resolvedor por-run barato (M74, Risco 1).\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- `CredentialStoreConfig` do subpath /auth resolve sob tsc; o projeto type-aware do eslint o lê como error-typed.\n return ensureFreshCredential(resolved, { config: this.config, store: this.store, env }, deps)\n }\n\n const caminho: string = authFilePath(this.store, env)\n\n // SINGLE-FLIGHT in-process, ANTES do lock (M74, EC-2 do edge-case review).\n //\n // `withFileLock` (proper-lockfile) NÃO é reentrante: se uma run começar de dentro de um contexto\n // que já segura o lock — uma run aninhada, ou um time disparando membros enquanto o pai refresca —\n // a segunda aquisição espera até o timeout e o sintoma é \"a run travou\", sem erro nenhum. Com o\n // resolvedor por-run do M74 isso deixa de ser hipotético: `ensureFresh` passa a ser chamado de\n // dentro do stream. A promise em voo faz a reentrância resolver por composição, não por lock.\n const emVoo = AuthProvider.refreshEmVoo.get(caminho)\n if (emVoo !== undefined) return emVoo\n\n const promessa = this.refrescarSobLock(caminho, resolved, deps, env)\n AuthProvider.refreshEmVoo.set(caminho, promessa)\n try {\n return await promessa\n } finally {\n AuthProvider.refreshEmVoo.delete(caminho)\n }\n }\n\n /** Refresh em voo por caminho de store — a chave é o arquivo, não a instância. */\n private static readonly refreshEmVoo = new Map<string, Promise<ResolvedCredential>>()\n\n /**\n * O refresh propriamente dito, serializado entre PROCESSOS e com re-leitura.\n *\n * A re-leitura não é detalhe: sem ela o lock apenas serializa, e o segundo processo decide com o\n * estado que leu ANTES de esperar — refrescando de novo e invalidando o token que o primeiro acabou\n * de gravar. É o double-checked locking clássico, e é o que o teste de dois processos pega.\n */\n private refrescarSobLock(\n caminho: string,\n resolved: ResolvedCredential,\n deps: EnsureFreshHttpDeps,\n env?: Record<string, string | undefined>,\n ): Promise<ResolvedCredential> {\n /* eslint-disable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access -- os subpaths `/auth` e `/persistence` do SDK resolvem sob tsc (typecheck da raiz limpo); o projeto type-aware do eslint os lê como error-typed. Mesma nota que este arquivo já carregava para `CredentialStoreConfig`. */\n return withFileLock(caminho, async () => {\n // RE-LEITURA depois de adquirir o lock: outro processo pode ter refrescado enquanto esperávamos.\n const doDisco = readStoredOAuth(this.store, env)\n const atual =\n doDisco !== undefined\n ? { ...resolved, apiKey: doDisco.access, expiresAt: doDisco.expires }\n : resolved\n return await ensureFreshCredential(\n atual,\n { config: this.config, store: this.store, env },\n deps,\n )\n }) as Promise<ResolvedCredential>\n /* eslint-enable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */\n }\n\n /**\n * Run the headless OpenAI device-login flow. Delegates to `openaiDeviceLogin` (which JWT-extracts the\n * account id). `deviceConfig` is passed per-call because it is a distinct endpoint set from the\n * refresh `config`. Returns `OAuthTokens` — the caller persists them via {@link AuthProvider.persist}.\n */\n deviceLogin(\n deviceConfig: OpenAIDeviceConfig,\n deps: DeviceLoginDeps,\n hooks: DeviceLoginHooks,\n ): Promise<OAuthTokens> {\n return openaiDeviceLogin(deviceConfig, deps, hooks)\n }\n\n /**\n * Persist freshly-obtained tokens through the held `store`. Delegates to `persistOAuthTokens` and\n * returns the credential-file path (never the token). `env` selects the store's home override.\n */\n persist(provider: string, tokens: OAuthTokens, env?: Record<string, string | undefined>): string {\n return persistOAuthTokens(provider, tokens, this.store, env)\n }\n}\n","// M60 — `@theokit/agents/auth`: the OO auth contract. `AuthProvider` (ENRICH — it holds the shared\n// `config`+`store` state and delegates to the SDK's free OAuth-lifecycle functions), plus the auth\n// domain's types re-exported so a consumer types the whole surface from the Theokit layer, never\n// reaching back to `@theokit/sdk/auth`.\nexport { AuthProvider } from './auth/auth-provider.js'\n\n// M73 — \"enriquecer nunca reduz\". A mecânica de store do SDK atravessa como PASS-THROUGH PURO.\n//\n// Antes disto, este subpath exportava 1 valor e 6 tipos enquanto `@theokit/sdk/auth` exportava 19\n// símbolos: nenhuma função atravessava. Como o consumidor tem regra INQUEBRÁVEL de nunca importar\n// `@theokit/sdk*` direto, **reimplementar era a única saída legal** — e o agent-builder reescreveu\n// seis destes nomes, ~120 linhas de mecânica duplicada. A lacuna era daqui, não indisciplina de lá.\n//\n// PURO, e não wrapper (parsimony Rung 9): estas são funções de I/O sem estado a segurar. A camada\n// enriquece onde há orquestração — é o que `AuthProvider` faz com o par `config`+`store`. Envolver\n// isto acrescentaria indireção sem nada dentro, e **quebraria `instanceof`**: o consumidor faz\n// `err instanceof CredentialError`, o que só vale enquanto a classe for a MESMA referência do SDK.\n// `tests/unit/auth-parity.test.ts` trava essa identidade com `toBe`.\n//\n// `resolveCredential` NÃO atravessa, de propósito: o SDK e o agent-builder têm funções DIFERENTES com\n// esse nome (sync vs async, lança vs `undefined`, lê env vs não lê, infere provider vs recusa), e o\n// próprio SDK declara que a precedência de env, a inferência por prefixo e o provider declarado são\n// app policy do consumidor (`internal/auth/credential-store.ts`). Expor os dois no mesmo escopo seria\n// convite a importar o errado, com falha silenciosa.\nexport {\n authFilePath,\n CredentialError,\n credentialHome,\n readAuthFile,\n readStoredOAuth,\n writeCredential,\n} from '@theokit/sdk/auth'\nexport type { ResolveCredentialOptions } from '@theokit/sdk/auth'\nexport type {\n CredentialStoreConfig,\n DeviceDeps,\n OAuthProviderConfig,\n OAuthTokens,\n OpenAIDeviceConfig,\n ResolvedCredential,\n} from '@theokit/sdk/auth'\n"],"mappings":";;;;;AAAA,SACEA,cACAC,uBACAC,mBACAC,oBACAC,uBACK;AAQP,SAASC,oBAAoB;AAiFtB,IAAMC,eAAN,MAAMA,cAAAA;EA/Fb,OA+FaA;;;;;EACX,YACmBC,QACAC,OACjB;SAFiBD,SAAAA;SACAC,QAAAA;EAChB;;;;;;EAOH,MAAMC,YACJC,UACAC,MACAC,KAC6B;AAC7B,QAAIF,SAASG,SAAS,SAAS;AAI7B,aAAOC,sBAAsBJ,UAAU;QAAEH,QAAQ,KAAKA;QAAQC,OAAO,KAAKA;QAAOI;MAAI,GAAGD,IAAAA;IAC1F;AAEA,UAAMI,UAAkBC,aAAa,KAAKR,OAAOI,GAAAA;AASjD,UAAMK,QAAQX,cAAaY,aAAaC,IAAIJ,OAAAA;AAC5C,QAAIE,UAAUG,OAAW,QAAOH;AAEhC,UAAMI,WAAW,KAAKC,iBAAiBP,SAASL,UAAUC,MAAMC,GAAAA;AAChEN,kBAAaY,aAAaK,IAAIR,SAASM,QAAAA;AACvC,QAAI;AACF,aAAO,MAAMA;IACf,UAAA;AACEf,oBAAaY,aAAaM,OAAOT,OAAAA;IACnC;EACF;;EAGA,OAAwBG,eAAe,oBAAIO,IAAAA;;;;;;;;EASnCH,iBACNP,SACAL,UACAC,MACAC,KAC6B;AAE7B,WAAOc,aAAaX,SAAS,YAAA;AAE3B,YAAMY,UAAUC,gBAAgB,KAAKpB,OAAOI,GAAAA;AAC5C,YAAMiB,QACJF,YAAYP,SACR;QAAE,GAAGV;QAAUoB,QAAQH,QAAQI;QAAQC,WAAWL,QAAQM;MAAQ,IAClEvB;AACN,aAAO,MAAMI,sBACXe,OACA;QAAEtB,QAAQ,KAAKA;QAAQC,OAAO,KAAKA;QAAOI;MAAI,GAC9CD,IAAAA;IAEJ,CAAA;EAEF;;;;;;EAOAuB,YACEC,cACAxB,MACAyB,OACsB;AACtB,WAAOC,kBAAkBF,cAAcxB,MAAMyB,KAAAA;EAC/C;;;;;EAMAE,QAAQC,UAAkBC,QAAqB5B,KAAkD;AAC/F,WAAO6B,mBAAmBF,UAAUC,QAAQ,KAAKhC,OAAOI,GAAAA;EAC1D;AACF;;;ACxKA,SACE8B,gBAAAA,eACAC,iBACAC,gBACAC,cACAC,mBAAAA,kBACAC,uBACK;","names":["authFilePath","ensureFreshCredential","openaiDeviceLogin","persistOAuthTokens","readStoredOAuth","withFileLock","AuthProvider","config","store","ensureFresh","resolved","deps","env","kind","ensureFreshCredential","caminho","authFilePath","emVoo","refreshEmVoo","get","undefined","promessa","refrescarSobLock","set","delete","Map","withFileLock","doDisco","readStoredOAuth","atual","apiKey","access","expiresAt","expires","deviceLogin","deviceConfig","hooks","openaiDeviceLogin","persist","provider","tokens","persistOAuthTokens","authFilePath","CredentialError","credentialHome","readAuthFile","readStoredOAuth","writeCredential"]}
@@ -938,13 +938,7 @@ interface RuntimeOverrides {
938
938
  */
939
939
  sdkTools?: readonly CustomTool[];
940
940
  }
941
- /**
942
- * Creates an agent stream factory using @theokit/sdk as the runtime.
943
- *
944
- * Returns a function that, given a message + sessionId, yields TheoKit
945
- * AgentStreamEvent via the SDK's Agent.create() + Run.stream() pipeline.
946
- */
947
- declare function createSdkAgentStream(compiled: CompiledAgentOptions, compiledTools: CompiledTool[], apiKey: string, overrides?: RuntimeOverrides): ((message: string, sessionId: string, factoryOpts?: {
941
+ declare function createSdkAgentStream(compiled: CompiledAgentOptions, compiledTools: CompiledTool[], apiKey: string | (() => string | Promise<string>), overrides?: RuntimeOverrides): ((message: string, sessionId: string, factoryOpts?: {
948
942
  disableTools?: boolean;
949
943
  }) => AsyncIterable<StreamEvent>) & {
950
944
  resolvedModel: string;
@@ -973,7 +967,7 @@ interface SdkAgentHandle {
973
967
  * surface (e.g. the ACP client) owns approval. Tools still execute; they are simply not HITL-gated here.
974
968
  */
975
969
  declare function toAgentFactory(def: AgentDefinition, opts: {
976
- apiKey: string;
970
+ apiKey: string | (() => string | Promise<string>);
977
971
  overrides?: RuntimeOverrides;
978
972
  }): (sessionId: string) => Promise<SdkAgentHandle>;
979
973
 
package/dist/bridge.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { g as AGENT_BRAND, h as AfterToolCallContext, i as AgentBuilder, j as AgentDefinition, k as AgentDefinitionError, l as AgentExecutionContext, m as AgentManifest, f as AgentManifestEntry, n as AgentManifestSource, o as AgentManifestTool, q as AgentRoute, r as AgentRouteContext, s as AgentRunInfo, t as AgentStreamEvent, u as AgentTurnMetadata, v as AgentsPluginOptions, w as ApiErrorContext, x as ApiErrorDecision, y as ApiErrorPolicy, z as ApprovalRequiredEvent, B as ArtifactChunkEvent, E as ArtifactStartEvent, F as BackgroundDelegation, I as BeforeToolCallContext, J as BudgetExceededError, N as CheckpointSavedEvent, C as CompiledAgentOptions, O as CompiledContextWindow, a as CompiledTool, P as ContextualTool, V as DefineAgentConfig, W as DelegateFn, X as DelegateOptions, Y as DelegationError, D as DelegationResult, Z as DoneEvent, _ as ErrorEvent, $ as FileEditEvent, a5 as InferAgentInput, a6 as InferAgentToolNames, a7 as IterationEvent, a8 as LLMCallContext, ad as McpApprovalSpec, ae as McpRegistryConfig, af as McpRequestContext, ag as McpSelection, ah as PartialToolCallEvent, aj as ProcessInputContext, an as RunStartedEvent, ao as ScoreVerdict, ap as ScoredDelegation, aq as Scorer, ar as SdkAgentHandle, as as SdkMessage, at as Segment, aw as StateUpdateEvent, S as StreamEvent, ax as TextDeltaEvent, ay as ThinkingEvent, aA as ToolCallEvent, aB as ToolCallVeto, aC as ToolHooks, aD as ToolHooksPlugin, aE as ToolResultEvent, aF as ToolWalkResult, aH as ToolboxWalkResult, aI as agentsPlugin, aJ as buildModelSelection, aK as compileAgentDefinition, aL as compileAgentModule, aM as compileContextWindow, aN as compileProjectContext, aO as compileSkills, aP as compileTools, aQ as createAgentExecutionContext, aR as createApiErrorHandler, aS as createSdkAgentStream, aT as createThinkTagExtractor, aU as createToolHooksPlugin, aV as delegate, aW as delegateBackground, aX as delegateWithScoring, aY as extractThinkTagStream, aZ as generateAgentManifest, a_ as generateAgentRoutes, a$ as isAgentContext, b0 as isAgentDefinition, b1 as isApprovalRequired, b2 as isDone, b3 as isError, b4 as isPartialToolCall, b5 as isTextDelta, b6 as isToolCall, b7 as isToolResult, ba as mcpRegistry, bb as mcpToolApprovals, bd as presentUIMessageStream, be as projectContextMetadataOnlyKnobs, bi as resolveMcpServers, bj as runWithApiErrorHandling, bk as streamAgentResponse, bl as streamAgentUIMessages, bm as toAgentFactory, bn as translateSdkEvent } from './bridge-entry-Ddu3Ug_3.js';
1
+ export { g as AGENT_BRAND, h as AfterToolCallContext, i as AgentBuilder, j as AgentDefinition, k as AgentDefinitionError, l as AgentExecutionContext, m as AgentManifest, f as AgentManifestEntry, n as AgentManifestSource, o as AgentManifestTool, q as AgentRoute, r as AgentRouteContext, s as AgentRunInfo, t as AgentStreamEvent, u as AgentTurnMetadata, v as AgentsPluginOptions, w as ApiErrorContext, x as ApiErrorDecision, y as ApiErrorPolicy, z as ApprovalRequiredEvent, B as ArtifactChunkEvent, E as ArtifactStartEvent, F as BackgroundDelegation, I as BeforeToolCallContext, J as BudgetExceededError, N as CheckpointSavedEvent, C as CompiledAgentOptions, O as CompiledContextWindow, a as CompiledTool, P as ContextualTool, V as DefineAgentConfig, W as DelegateFn, X as DelegateOptions, Y as DelegationError, D as DelegationResult, Z as DoneEvent, _ as ErrorEvent, $ as FileEditEvent, a5 as InferAgentInput, a6 as InferAgentToolNames, a7 as IterationEvent, a8 as LLMCallContext, ad as McpApprovalSpec, ae as McpRegistryConfig, af as McpRequestContext, ag as McpSelection, ah as PartialToolCallEvent, aj as ProcessInputContext, an as RunStartedEvent, ao as ScoreVerdict, ap as ScoredDelegation, aq as Scorer, ar as SdkAgentHandle, as as SdkMessage, at as Segment, aw as StateUpdateEvent, S as StreamEvent, ax as TextDeltaEvent, ay as ThinkingEvent, aA as ToolCallEvent, aB as ToolCallVeto, aC as ToolHooks, aD as ToolHooksPlugin, aE as ToolResultEvent, aF as ToolWalkResult, aH as ToolboxWalkResult, aI as agentsPlugin, aJ as buildModelSelection, aK as compileAgentDefinition, aL as compileAgentModule, aM as compileContextWindow, aN as compileProjectContext, aO as compileSkills, aP as compileTools, aQ as createAgentExecutionContext, aR as createApiErrorHandler, aS as createSdkAgentStream, aT as createThinkTagExtractor, aU as createToolHooksPlugin, aV as delegate, aW as delegateBackground, aX as delegateWithScoring, aY as extractThinkTagStream, aZ as generateAgentManifest, a_ as generateAgentRoutes, a$ as isAgentContext, b0 as isAgentDefinition, b1 as isApprovalRequired, b2 as isDone, b3 as isError, b4 as isPartialToolCall, b5 as isTextDelta, b6 as isToolCall, b7 as isToolResult, ba as mcpRegistry, bb as mcpToolApprovals, bd as presentUIMessageStream, be as projectContextMetadataOnlyKnobs, bi as resolveMcpServers, bj as runWithApiErrorHandling, bk as streamAgentResponse, bl as streamAgentUIMessages, bm as toAgentFactory, bn as translateSdkEvent } from './bridge-entry-BmPk3TPf.js';
2
2
  import '@theokit/http';
3
3
  import '@theokit/sdk';
4
4
  import 'zod';
package/dist/bridge.js CHANGED
@@ -43,7 +43,7 @@ import {
43
43
  streamAgentUIMessages,
44
44
  toAgentFactory,
45
45
  translateSdkEvent
46
- } from "./chunk-LIRSFEEJ.js";
46
+ } from "./chunk-ZQKR6XQS.js";
47
47
  import "./chunk-7QVYU63E.js";
48
48
  export {
49
49
  AGENT_BRAND,
@@ -1164,6 +1164,10 @@ function buildSdkTools(compiledTools, defineTool, extraSdkTools = [], runContext
1164
1164
  ];
1165
1165
  }
1166
1166
  __name(buildSdkTools, "buildSdkTools");
1167
+ async function resolverApiKey(k) {
1168
+ return typeof k === "function" ? await k() : k;
1169
+ }
1170
+ __name(resolverApiKey, "resolverApiKey");
1167
1171
  function createSdkAgentStream(compiled, compiledTools, apiKey, overrides = {}) {
1168
1172
  const model = overrides.model ?? compiled.model ?? "openai/gpt-4o-mini";
1169
1173
  const reasoningEffort = overrides.reasoningEffort ?? compiled.reasoningEffort;
@@ -1201,8 +1205,9 @@ function createSdkAgentStream(compiled, compiledTools, apiKey, overrides = {}) {
1201
1205
  keys: runContext !== void 0 ? Object.keys(runContext) : []
1202
1206
  });
1203
1207
  try {
1208
+ const apiKeyResolvida = await resolverApiKey(apiKey);
1204
1209
  yield* streamSdkAgent(rt, compiled, sdkTools, {
1205
- apiKey,
1210
+ apiKey: apiKeyResolvida,
1206
1211
  model,
1207
1212
  reasoningEffort,
1208
1213
  overrides,
@@ -1310,8 +1315,9 @@ function toAgentFactory(def, opts) {
1310
1315
  baseDir: overrides.baseDir
1311
1316
  };
1312
1317
  const extra = buildExtraCreateOptions(overrides, compiled);
1318
+ const apiKeyResolvida = await resolverApiKey(opts.apiKey);
1313
1319
  const agent = await rt.Agent.getOrCreate(sessionId, {
1314
- apiKey: opts.apiKey,
1320
+ apiKey: apiKeyResolvida,
1315
1321
  model: buildModelSelection(model, reasoningEffort),
1316
1322
  tools: sdkTools,
1317
1323
  ...m8,
@@ -3505,4 +3511,4 @@ export {
3505
3511
  generateAgentManifest,
3506
3512
  agentsPlugin
3507
3513
  };
3508
- //# sourceMappingURL=chunk-LIRSFEEJ.js.map
3514
+ //# sourceMappingURL=chunk-ZQKR6XQS.js.map