@theokit/agents 7.3.1 → 7.4.1

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.
@@ -85,20 +85,20 @@ interface InProcessTransportOptions {
85
85
  * `sendMessages` promise — whereas `HttpTransport` throws from `sendMessages` on a non-2xx response.
86
86
  */
87
87
  /**
88
- * Uma aprovação estacionada foi descartada porque o turno terminou sem decisão.
88
+ * A parked approval was discarded because the turn ended with no decision.
89
89
  *
90
- * M92 — tipado de propósito. Antes a promessa simplesmente **nunca** resolvia, e a chamada de tool do
91
- * SDK pendurava; `resolve(false)` seria pior ainda, porque é indistinguível de "o usuário negou".
90
+ * M92 — typed on purpose. Before, the promise simply **never** settled and the SDK tool call hung;
91
+ * `resolve(false)` would be worse still, because it is indistinguishable from "the user denied".
92
92
  */
93
93
  declare class ApprovalAbortedError extends Error {
94
94
  readonly approvalId: string;
95
- constructor(approvalId: string, motivo: string);
95
+ constructor(approvalId: string, reason: string);
96
96
  }
97
97
  declare class InProcessTransport implements AgentTransport {
98
98
  #private;
99
99
  constructor(options: InProcessTransportOptions);
100
- /** Quantas aprovações estão estacionadas. Existe para o teste poder provar a eviction. */
101
- get pendentes(): number;
100
+ /** How many approvals are parked. Exists so the test can prove the eviction. */
101
+ get pending(): number;
102
102
  sendMessages(options: Parameters<WireTransport['sendMessages']>[0]): Promise<ReadableStream<WireChunk>>;
103
103
  reconnectToStream(): Promise<ReadableStream<WireChunk> | null>;
104
104
  approve(approvalId: string, decision: ApprovalDecision): Promise<void>;
@@ -181,14 +181,14 @@ interface AgentClientState {
181
181
  * framework-agnostic, it is unit-tested without a DOM.
182
182
  */
183
183
  /**
184
- * M92 — opções do cliente. Aditivo: sem elas, o comportamento é o de sempre.
184
+ * M92 — client options. Additive: without them, the behaviour is exactly as before.
185
185
  */
186
186
  interface AgentClientOptions {
187
187
  /**
188
- * Janela de coalescing em ms. `0` ou ausente = emite por delta de token (comportamento pré-M92).
188
+ * Coalescing window in ms. `0` or absent = emit per token delta (the pre-M92 behaviour).
189
189
  *
190
- * Opt-in de propósito: este é um pacote publicado, e mudar a frequência de emit por padrão mudaria o
191
- * comportamento observável de quem conta emits ou depende da latência do primeiro token.
190
+ * Opt-in on purpose: this is a published package, and changing the emit frequency by default would
191
+ * change the observable behaviour of anyone counting emits or depending on first-token latency.
192
192
  */
193
193
  readonly emitIntervalMs?: number;
194
194
  }
package/dist/auth.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { OAuthProviderConfig, CredentialStoreConfig, ResolvedCredential, ensureFreshCredential, OpenAIDeviceConfig, openaiDeviceLogin, OAuthTokens, DeviceDeps } from '@theokit/sdk/auth';
2
- export { CredentialError, CredentialStoreConfig, DeviceCodeGrant, DeviceDeps, DeviceOAuthConfig, OAuthProviderConfig, OAuthTokens, OpenAIDeviceConfig, ResolveCredentialOptions, ResolvedCredential, authFilePath, credentialHome, deviceLogin, openaiDeviceLogin, pollDeviceToken, readAuthFile, readStoredOAuth, requestDeviceCode, writeCredential } from '@theokit/sdk/auth';
2
+ export { CredentialError, CredentialStoreConfig, DeviceCodeGrant, DeviceDeps, DeviceOAuthConfig, OAuthProviderConfig, OAuthTokens, OpenAIDeviceConfig, ResolveCredentialOptions, ResolvedCredential, authFilePath, credentialHome, deviceLogin, ensureFreshCredential, extractAccountId, openaiDeviceLogin, persistOAuthTokens, pollDeviceToken, readAuthFile, readStoredOAuth, refreshOAuthTokens, requestDeviceCode, writeCredential } from '@theokit/sdk/auth';
3
3
 
4
4
  /**
5
5
  * M60 — `AuthProvider`, the OO contract that unifies the SDK's free OAuth-lifecycle functions
@@ -31,16 +31,17 @@ 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;
34
+ /** In-flight refresh per store paththe key is the file, not the instance. */
35
+ private static readonly refreshInFlight;
36
36
  /**
37
- * O refresh propriamente dito, serializado entre PROCESSOS e com re-leitura.
37
+ * The refresh itself, serialized across PROCESSES and with a re-read.
38
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 esperarrefrescando 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.
39
+ * The re-read is not a detail: without it the lock merely serializes, and the second process
40
+ * decides using the state it read BEFORE waiting refreshing again and invalidating the token the
41
+ * first one just wrote. It is classic double-checked locking, and it is what the two-process test
42
+ * catches.
42
43
  */
43
- private refrescarSobLock;
44
+ private refreshUnderLock;
44
45
  /**
45
46
  * Run the headless OpenAI device-login flow. Delegates to `openaiDeviceLogin` (which JWT-extracts the
46
47
  * account id). `deviceConfig` is passed per-call because it is a distinct endpoint set from the
@@ -55,60 +56,61 @@ declare class AuthProvider {
55
56
  }
56
57
 
57
58
  /**
58
- * M111 — device auth plug-and-play: um provider é um objeto com métodos ROTULADOS, e um login cabe
59
- * numa chamada.
59
+ * M111 — device auth plug-and-play: a provider is an object with LABELLED methods, and a login fits
60
+ * in one call.
60
61
  *
61
- * ## O problema, medido
62
+ * ## The problem, measured
62
63
  *
63
- * O M110 fez o device flow RFC 8628 atravessar esta camada. Ele não tocou a ergonomia: para
64
- * autenticar no Codex, o consumidor precisava saber que existem **duas** formas de device flow,
65
- * copiar um `clientId` e três URLs da OpenAI para dentro do próprio código, montar
66
- * `{ fetch, sleep, now }`, chamar `deviceLogin` e **lembrar** de chamar `persist` — e esquecer o
67
- * último custa um round-trip OAuth completo que não guarda nada. O docblock de `AuthProvider`
68
- * instruía exatamente isso: *"the caller persists them via `AuthProvider.persist`"*.
64
+ * M110 made the RFC 8628 device flow cross this layer. It did not touch the ergonomics: to
65
+ * authenticate against Codex, the consumer had to know that **two** device-flow shapes exist, copy a
66
+ * `clientId` and three OpenAI URLs into its own code, assemble `{ fetch, sleep, now }`, call
67
+ * `deviceLogin` and **remember** to call `persist` — and forgetting the last one costs a full OAuth
68
+ * round-trip that stores nothing. The `AuthProvider` docblock instructed exactly that:
69
+ * *"the caller persists them via `AuthProvider.persist`"*.
69
70
  *
70
- * ## O desenho veio de medição contra três peers, e refutou a proposta original
71
+ * ## The design came from measuring three peers, and it refuted the original proposal
71
72
  *
72
- * - **`codex`** — `codex-rs/login/src/device_code_auth.rs:234` tem `run_device_code_login`, que
73
- * retorna `()`: **nada** sai para o chamador persistir, e as duas metades granulares continuam
74
- * públicas. `loginWithDevice` é a cópia dessa forma.
75
- * - **`opencode`** — cada provider é um objeto com `methods: [{ label, type, authorize }]`, e três
76
- * providers escritos por autores diferentes convergem em **3 métodos rotulados** cada. O rótulo é o
77
- * que a UI mostra: transforma escolha de protocolo em escolha de frase legível.
78
- * - **REJEITADOdiscriminante `kind`.** Nenhum dos três discrimina protocolo por campo. A medição
79
- * que fecha o caso: no `opencode`, browser e headless do Codex carregam o **mesmo** `type: 'oauth'`
80
- * — logo o `type` classifica **espécie de credencial**, não protocolo. Um `kind` com despacho
81
- * interno seria um `switch`, exatamente o defeito que este milestone remove do consumidor.
82
- * Aqui, cada método aponta para a **sua própria** função.
73
+ * - **`codex`** — `codex-rs/login/src/device_code_auth.rs:234` has `run_device_code_login`, which
74
+ * returns `()`: **nothing** comes out for the caller to persist, and the two granular halves stay
75
+ * public. `loginWithDevice` copies that shape.
76
+ * - **`opencode`** — every provider is an object with `methods: [{ label, type, authorize }]`, and
77
+ * three providers written by different authors converge on **3 labelled methods** each. The label
78
+ * is what the UI shows: it turns a protocol choice into a choice between readable phrases.
79
+ * - **REJECTEDa `kind` discriminant.** None of the three discriminates protocol by field. The
80
+ * measurement that closes the case: in `opencode`, Codex's browser and headless methods carry the
81
+ * **same** `type: 'oauth'` so `type` classifies the **kind of credential**, not the protocol. A
82
+ * `kind` with internal dispatch would be a `switch`, exactly the defect this milestone removes
83
+ * from the consumer. Here, each method points at **its own** function.
83
84
  *
84
- * ## Por que a identidade pública mora AQUI
85
+ * ## Why the public identity lives HERE
85
86
  *
86
- * `codex` exporta `CLIENT_ID` do crate que implementa o flow (`login/src/lib.rs:32`) e o CLI o
87
- * **importa**; o `opencode` o declara dentro do plugin. Os dois chegaram ao mesmo lugar
88
- * independentementee com o mesmo valor que o consumidor tinha copiado. Enquanto morasse no
89
- * consumidor, todo projeto que quisesse Codex copiaria quatro constantes públicas: é violação de DRY
90
- * através da fronteira, com dois donos do mesmo fato.
87
+ * `codex` exports `CLIENT_ID` from the crate that implements the flow (`login/src/lib.rs:32`) and
88
+ * the CLI **imports** it; `opencode` declares it inside the plugin. The two arrived at the same
89
+ * place independently and with the same value the consumer had copied. As long as it lived in the
90
+ * consumer, every project wanting Codex would copy four public constants: a DRY violation across the
91
+ * boundary, with two owners of the same fact.
91
92
  */
92
93
  /**
93
- * Uma forma rotulada de obter credencial dentro de um provider.
94
+ * A labelled way of obtaining a credential within a provider.
94
95
  *
95
- * UNIÃO DISCRIMINADA, não um campo `authorize?` opcional. Com opcional, `{ label, type: 'oauth' }`
96
- * seria representável um método OAuth que não sabe autorizar, detectado em runtime, no meio do
97
- * login do usuário. É a alternativa que o M110 rejeitou por escrito ao recusar "um tipo só com
98
- * campos opcionais": tornaria representável um config inválido e moveria a detecção do compilador
96
+ * A DISCRIMINATED UNION, not an optional `authorize?` field. With an optional field,
97
+ * `{ label, type: 'oauth' }` would be representable an OAuth method that cannot authorize,
98
+ * detected only at runtime, in the middle of the user's login. It is the alternative M110 already
99
+ * rejected in writing when it refused "one type with optional fields": it would make an invalid
100
+ * config representable and move detection out of the compiler
99
101
  * para o runtime.
100
102
  */
101
103
  type AuthMethod = {
102
- /** O que a interface mostra ao usuário. É a peça que torna o fluxo escolhível sem saber o protocolo. */
104
+ /** What the interface shows the user. The piece that makes the flow choosable without knowing the protocol. */
103
105
  readonly label: string;
104
106
  readonly type: 'oauth';
105
- /** A função DESTE método. Sem discriminante: o método aponta para a sua, não para um `switch`. */
107
+ /** THIS method's function. No discriminant: the method points at its own, not at a `switch`. */
106
108
  readonly authorize: (deps: DeviceDeps, hooks: PromptHooks) => Promise<OAuthTokens>;
107
109
  } | {
108
110
  readonly label: string;
109
111
  readonly type: 'api';
110
112
  };
111
- /** O que o consumidor liga à sua UI para mostrar o código que o usuário digita no outro dispositivo. */
113
+ /** What the consumer wires into its UI to show the code the user types on the other device. */
112
114
  interface PromptHooks {
113
115
  onPrompt: (p: {
114
116
  userCode: string;
@@ -116,50 +118,50 @@ interface PromptHooks {
116
118
  expiresIn?: number;
117
119
  }) => void;
118
120
  }
119
- /** Um provider de autenticação: identidade pública + as formas rotuladas de autenticar nele. */
121
+ /** An authentication provider: public identity + the labelled ways of authenticating with it. */
120
122
  interface DeviceAuthProvider {
121
123
  readonly name: string;
122
124
  readonly oauth: OAuthProviderConfig;
123
125
  readonly methods: readonly AuthMethod[];
124
126
  }
125
127
  /**
126
- * Override do `clientId` por ambiente adotado do `codex`, que exporta `CLIENT_ID` **e**
127
- * `CLIENT_ID_OVERRIDE_ENV_VAR` (`login/src/lib.rs:32-33`). Dissolve o falso dilema entre constante
128
- * fixa (inflexível) e parâmetro obrigatório (que devolve a cópia ao consumidor): default no pacote,
129
- * escape para quem precisa.
128
+ * Environment override for `clientId` — adopted from `codex`, which exports `CLIENT_ID` **and**
129
+ * `CLIENT_ID_OVERRIDE_ENV_VAR` (`login/src/lib.rs:32-33`). It dissolves the false dilemma between a
130
+ * fixed constant (inflexible) and a mandatory parameter (which hands the copy back to the consumer):
131
+ * a default in the package, an escape for whoever needs one.
130
132
  */
131
133
  declare const CODEX_CLIENT_ID_ENV_VAR = "THEOKIT_CODEX_CLIENT_ID";
132
134
  /**
133
- * O provider do Codex, montado e **congelado**.
135
+ * The Codex provider, assembled and **frozen**.
134
136
  *
135
- * Congelado porque é identidade pública COMPARTILHADA no processo: um consumidor que a mutasse
136
- * mudaria o login de todos os outros. `Object.freeze` é raso, então a lista de métodos é congelada
137
- * separadamentesem isso, `CODEX_PROVIDER.methods.push(...)` passaria.
137
+ * Frozen because it is a public identity SHARED across the process: a consumer that mutated it
138
+ * would change everyone else's login. `Object.freeze` is shallow, so the method list is frozen
139
+ * separatelywithout that, `CODEX_PROVIDER.methods.push(...)` would go through.
138
140
  */
139
141
  declare const CODEX_PROVIDER: DeviceAuthProvider;
140
142
  /**
141
- * Opções do Facade. `deps` e `env` viajam juntos num objeto em vez de dois parâmetros posicionais:
142
- * ambos são opcionais e raramente usados, e seis posicionais é assinatura que o chamador erra em
143
- * silêncio (o lint do monorepo cobra 5 como tetoo teto existe por este motivo).
143
+ * Facade options. `deps` and `env` travel together in one object rather than as two positional
144
+ * parameters: both are optional and rarely used, and six positionals is a signature callers get
145
+ * wrong in silence (the monorepo lint enforces 5 as the ceiling the ceiling exists for this reason).
144
146
  */
145
147
  interface LoginWithDeviceOptions {
146
- /** Injeção de I/O para teste. Omitido, usa `fetch`/`setTimeout`/`Date.now` reais. */
148
+ /** I/O injection for tests. Omitted, it uses the real `fetch`/`setTimeout`/`Date.now`. */
147
149
  readonly deps?: Partial<DeviceDeps>;
148
- /** Ambiente lido pelo store para resolver o diretório da credencial. */
150
+ /** The environment the store reads to resolve the credential directory. */
149
151
  readonly env?: Record<string, string | undefined>;
150
152
  }
151
153
  /**
152
- * Autoriza **e** persiste, numa chamada. Devolve onde a credencial ficou e a conta atribuída —
153
- * **nunca** material de token.
154
+ * Authorizes **and** persists, in one call. Returns where the credential landed and the account it
155
+ * was attributed to — **never** token material.
154
156
  *
155
- * A forma vem de `run_device_code_login` (`codex`), que retorna `()`: se nada sai para o chamador,
156
- * não passo que ele possa esquecer. As duas metades continuam públicas em `AuthProvider`
157
- * (`deviceLogin` / `persist`) para quem precisa da granularidademesma escolha que o `codex` faz ao
158
- * manter `request_device_code` e `complete_device_code_login` públicas ao lado do Facade.
157
+ * The shape comes from `run_device_code_login` (`codex`), which returns `()`: if nothing comes out
158
+ * for the caller, there is no step it can forget. The two halves stay public on `AuthProvider`
159
+ * (`deviceLogin` / `persist`) for whoever needs the granularitythe same choice `codex` makes by
160
+ * keeping `request_device_code` and `complete_device_code_login` public alongside the facade.
159
161
  *
160
- * Delega verbatim: `method.authorize` roda o flow e `AuthProvider.persist` grava. Copiar a sequência
161
- * em vez de chamá-la criaria um segundo oráculo sobre o mesmo fato, e dois oráculos divergem no
162
- * primeiro fix aplicado a um lado só.
162
+ * It delegates verbatim: `method.authorize` runs the flow and `AuthProvider.persist` writes. Copying
163
+ * the sequence instead of calling it would create a second oracle over the same fact, and two oracles
164
+ * diverge on the first fix applied to only one side.
163
165
  */
164
166
  declare function loginWithDevice(provider: DeviceAuthProvider, method: AuthMethod, store: CredentialStoreConfig, hooks: PromptHooks, opts?: LoginWithDeviceOptions): Promise<{
165
167
  path: string;
package/dist/auth.js CHANGED
@@ -1,21 +1,21 @@
1
- import {
2
- __name
3
- } from "./chunk-Z4QWC7IK.js";
4
-
5
1
  // src/auth/auth-provider.ts
6
- import { authFilePath, ensureFreshCredential, openaiDeviceLogin, persistOAuthTokens, readStoredOAuth } from "@theokit/sdk/auth";
2
+ import {
3
+ authFilePath,
4
+ ensureFreshCredential,
5
+ openaiDeviceLogin,
6
+ persistOAuthTokens,
7
+ readStoredOAuth
8
+ } from "@theokit/sdk/auth";
7
9
  import { withFileLock } from "@theokit/sdk/persistence";
8
10
  var RefreshFailure = class extends Error {
9
- static {
10
- __name(this, "RefreshFailure");
11
- }
12
- transitorio;
13
- constructor(message, transitorio) {
14
- super(message), this.transitorio = transitorio;
11
+ constructor(message, transient) {
12
+ super(message);
13
+ this.transient = transient;
15
14
  this.name = "RefreshFailure";
16
15
  }
16
+ transient;
17
17
  };
18
- var MOTIVOS_TRANSITORIOS = [
18
+ var TRANSIENT_REASONS = [
19
19
  "ETIMEDOUT",
20
20
  "ECONNRESET",
21
21
  "ECONNREFUSED",
@@ -23,107 +23,119 @@ var MOTIVOS_TRANSITORIOS = [
23
23
  "ENOTFOUND",
24
24
  "AbortError"
25
25
  ];
26
- function classificarFalhaDeRefresh(err) {
27
- const texto = err instanceof Error ? `${err.name}: ${err.message}` : String(err);
28
- if (/invalid_grant|invalid_request|unauthorized_client/i.test(texto)) {
29
- return new RefreshFailure("o refresh token n\xE3o \xE9 mais v\xE1lido \u2014 refa\xE7a o login. Tentar de novo n\xE3o muda o resultado.", false);
26
+ function classifyRefreshFailure(err) {
27
+ const text = err instanceof Error ? `${err.name}: ${err.message}` : String(err);
28
+ if (/invalid_grant|invalid_request|unauthorized_client/i.test(text)) {
29
+ return new RefreshFailure(
30
+ "the refresh token is no longer valid \u2014 log in again. Retrying does not change the outcome.",
31
+ false
32
+ );
30
33
  }
31
- const transitorio = MOTIVOS_TRANSITORIOS.some((m) => texto.includes(m)) || /\b(5\d{2})\b|timeout|network/i.test(texto);
32
- return new RefreshFailure(transitorio ? "falha transit\xF3ria ao refrescar a credencial" : "falha ao refrescar a credencial", transitorio);
34
+ const transient = TRANSIENT_REASONS.some((m) => text.includes(m)) || /\b(5\d{2})\b|timeout|network/i.test(text);
35
+ return new RefreshFailure(
36
+ transient ? "transient failure refreshing the credential" : "failure refreshing the credential",
37
+ transient
38
+ );
33
39
  }
34
- __name(classificarFalhaDeRefresh, "classificarFalhaDeRefresh");
35
- function esperaComJitter(tentativa, baseMs = 200, aleatorio = Math.random) {
36
- const base = baseMs * 2 ** tentativa;
37
- return Math.round(base * (0.75 + aleatorio() * 0.5));
40
+ function waitWithJitter(attempt, baseMs = 200, random = Math.random) {
41
+ const base = baseMs * 2 ** attempt;
42
+ return Math.round(base * (0.75 + random() * 0.5));
38
43
  }
39
- __name(esperaComJitter, "esperaComJitter");
40
44
  var AuthProvider = class _AuthProvider {
41
- static {
42
- __name(this, "AuthProvider");
43
- }
44
- config;
45
- store;
46
45
  constructor(config, store) {
47
46
  this.config = config;
48
47
  this.store = store;
49
48
  }
49
+ config;
50
+ store;
50
51
  /**
51
- * Refresh a resolved credential if stale. Delegates to `ensureFreshCredential` with the held
52
- * `config` + `store`; `env` (for reading the store's env overrides) + the `{ fetch, now }` HTTP deps
53
- * thread through. Returns the fresh `ResolvedCredential` — never logs the rotated token.
54
- */
52
+ * Refresh a resolved credential if stale. Delegates to `ensureFreshCredential` with the held
53
+ * `config` + `store`; `env` (for reading the store's env overrides) + the `{ fetch, now }` HTTP deps
54
+ * thread through. Returns the fresh `ResolvedCredential` — never logs the rotated token.
55
+ */
55
56
  async ensureFresh(resolved, deps, env) {
56
57
  if (resolved.kind !== "oauth") {
57
- return ensureFreshCredential(resolved, {
58
- config: this.config,
59
- store: this.store,
60
- env
61
- }, deps);
58
+ return ensureFreshCredential(resolved, { config: this.config, store: this.store, env }, deps);
62
59
  }
63
- const caminho = authFilePath(this.store, env);
64
- const emVoo = _AuthProvider.refreshEmVoo.get(caminho);
65
- if (emVoo !== void 0) return emVoo;
66
- const promessa = this.refrescarSobLock(caminho, resolved, deps, env);
67
- _AuthProvider.refreshEmVoo.set(caminho, promessa);
60
+ const filePath = authFilePath(this.store, env);
61
+ const inFlight = _AuthProvider.refreshInFlight.get(filePath);
62
+ if (inFlight !== void 0) return inFlight;
63
+ const promise = this.refreshUnderLock(filePath, resolved, deps, env);
64
+ _AuthProvider.refreshInFlight.set(filePath, promise);
68
65
  try {
69
- return await promessa;
66
+ return await promise;
70
67
  } finally {
71
- _AuthProvider.refreshEmVoo.delete(caminho);
68
+ _AuthProvider.refreshInFlight.delete(filePath);
72
69
  }
73
70
  }
74
- /** Refresh em voo por caminho de store a chave é o arquivo, não a instância. */
75
- static refreshEmVoo = /* @__PURE__ */ new Map();
71
+ /** In-flight refresh per store paththe key is the file, not the instance. */
72
+ static refreshInFlight = /* @__PURE__ */ new Map();
76
73
  /**
77
- * O refresh propriamente dito, serializado entre PROCESSOS e com re-leitura.
78
- *
79
- * A re-leitura não é detalhe: sem ela o lock apenas serializa, e o segundo processo decide com o
80
- * estado que leu ANTES de esperarrefrescando de novo e invalidando o token que o primeiro acabou
81
- * de gravar. É o double-checked locking clássico, e é o que o teste de dois processos pega.
82
- */
83
- refrescarSobLock(caminho, resolved, deps, env) {
84
- return withFileLock(caminho, async () => {
74
+ * The refresh itself, serialized across PROCESSES and with a re-read.
75
+ *
76
+ * The re-read is not a detail: without it the lock merely serializes, and the second process
77
+ * decides using the state it read BEFORE waiting refreshing again and invalidating the token the
78
+ * first one just wrote. It is classic double-checked locking, and it is what the two-process test
79
+ * catches.
80
+ */
81
+ refreshUnderLock(filePath, resolved, deps, env) {
82
+ return withFileLock(filePath, async () => {
85
83
  const doDisco = readStoredOAuth(this.store, env);
86
- const atual = doDisco !== void 0 ? {
87
- ...resolved,
88
- apiKey: doDisco.access,
89
- expiresAt: doDisco.expires
90
- } : resolved;
91
- const MAX_TENTATIVAS = 3;
92
- for (let tentativa = 0; ; tentativa++) {
84
+ const current = doDisco !== void 0 ? { ...resolved, apiKey: doDisco.access, expiresAt: doDisco.expires } : resolved;
85
+ const MAX_ATTEMPTS = 3;
86
+ for (let attempt = 0; ; attempt++) {
93
87
  try {
94
- return await ensureFreshCredential(atual, {
95
- config: this.config,
96
- store: this.store,
97
- env
98
- }, deps);
88
+ return await ensureFreshCredential(
89
+ current,
90
+ { config: this.config, store: this.store, env },
91
+ deps
92
+ );
99
93
  } catch (err) {
100
- const falha = classificarFalhaDeRefresh(err);
101
- if (!falha.transitorio || tentativa >= MAX_TENTATIVAS - 1) throw falha;
102
- await new Promise((resolve) => setTimeout(resolve, esperaComJitter(tentativa)));
94
+ const failure = classifyRefreshFailure(err);
95
+ if (!failure.transient || attempt >= MAX_ATTEMPTS - 1) throw failure;
96
+ await new Promise((resolve) => setTimeout(resolve, waitWithJitter(attempt)));
103
97
  }
104
98
  }
105
99
  });
106
100
  }
107
101
  /**
108
- * Run the headless OpenAI device-login flow. Delegates to `openaiDeviceLogin` (which JWT-extracts the
109
- * account id). `deviceConfig` is passed per-call because it is a distinct endpoint set from the
110
- * refresh `config`. Returns `OAuthTokens` — the caller persists them via {@link AuthProvider.persist}.
111
- */
102
+ * Run the headless OpenAI device-login flow. Delegates to `openaiDeviceLogin` (which JWT-extracts the
103
+ * account id). `deviceConfig` is passed per-call because it is a distinct endpoint set from the
104
+ * refresh `config`. Returns `OAuthTokens` — the caller persists them via {@link AuthProvider.persist}.
105
+ */
112
106
  deviceLogin(deviceConfig, deps, hooks) {
113
107
  return openaiDeviceLogin(deviceConfig, deps, hooks);
114
108
  }
115
109
  /**
116
- * Persist freshly-obtained tokens through the held `store`. Delegates to `persistOAuthTokens` and
117
- * returns the credential-file path (never the token). `env` selects the store's home override.
118
- */
110
+ * Persist freshly-obtained tokens through the held `store`. Delegates to `persistOAuthTokens` and
111
+ * returns the credential-file path (never the token). `env` selects the store's home override.
112
+ */
119
113
  persist(provider, tokens, env) {
120
114
  return persistOAuthTokens(provider, tokens, this.store, env);
121
115
  }
122
116
  };
123
117
 
124
118
  // src/auth-entry.ts
125
- import { authFilePath as authFilePath2, CredentialError, credentialHome, readAuthFile, readStoredOAuth as readStoredOAuth2, writeCredential } from "@theokit/sdk/auth";
126
- import { deviceLogin, openaiDeviceLogin as openaiDeviceLogin3, pollDeviceToken, requestDeviceCode } from "@theokit/sdk/auth";
119
+ import {
120
+ authFilePath as authFilePath2,
121
+ CredentialError,
122
+ credentialHome,
123
+ readAuthFile,
124
+ readStoredOAuth as readStoredOAuth2,
125
+ writeCredential
126
+ } from "@theokit/sdk/auth";
127
+ import {
128
+ deviceLogin,
129
+ openaiDeviceLogin as openaiDeviceLogin3,
130
+ pollDeviceToken,
131
+ requestDeviceCode
132
+ } from "@theokit/sdk/auth";
133
+ import {
134
+ ensureFreshCredential as ensureFreshCredential2,
135
+ extractAccountId,
136
+ persistOAuthTokens as persistOAuthTokens2,
137
+ refreshOAuthTokens
138
+ } from "@theokit/sdk/auth";
127
139
 
128
140
  // src/auth/device-provider.ts
129
141
  import { openaiDeviceLogin as openaiDeviceLogin2 } from "@theokit/sdk/auth";
@@ -135,12 +147,7 @@ var CODEX_OAUTH = {
135
147
  clientId: process.env[CODEX_CLIENT_ID_ENV_VAR] ?? CODEX_CLIENT_ID,
136
148
  authorizeEndpoint: `${CODEX_ISSUER}/oauth/authorize`,
137
149
  tokenEndpoint: `${CODEX_ISSUER}/oauth/token`,
138
- scopes: [
139
- "openid",
140
- "profile",
141
- "email",
142
- "offline_access"
143
- ],
150
+ scopes: ["openid", "profile", "email", "offline_access"],
144
151
  redirectUri: `${CODEX_ISSUER}/deviceauth/callback`
145
152
  };
146
153
  var CODEX_DEVICE = {
@@ -156,9 +163,9 @@ var CODEX_PROVIDER = Object.freeze({
156
163
  Object.freeze({
157
164
  label: "ChatGPT Pro/Plus (headless device code)",
158
165
  type: "oauth",
159
- // Aponta para a variante da OpenAI. Um provider RFC 8628 apontaria para `deviceLogin`, e é
160
- // assim que as duas formas coexistem sem discriminante.
161
- authorize: /* @__PURE__ */ __name((deps, hooks) => openaiDeviceLogin2(CODEX_DEVICE, deps, hooks), "authorize")
166
+ // Points at OpenAI's variant. An RFC 8628 provider would point at `deviceLogin`, and that is
167
+ // how the two shapes coexist with no discriminant.
168
+ authorize: (deps, hooks) => openaiDeviceLogin2(CODEX_DEVICE, deps, hooks)
162
169
  }),
163
170
  Object.freeze({
164
171
  label: "Manually enter API Key",
@@ -173,27 +180,24 @@ function comDefaults(deps) {
173
180
  now: deps?.now ?? Date.now
174
181
  };
175
182
  }
176
- __name(comDefaults, "comDefaults");
177
183
  async function loginWithDevice(provider, method, store, hooks, opts = {}) {
178
184
  if (provider.methods.length === 0) {
179
- throw new TypeError(`o provider "${provider.name}" declara nenhum m\xE9todo de autentica\xE7\xE3o \u2014 n\xE3o h\xE1 o que escolher`);
185
+ throw new TypeError(
186
+ `provider "${provider.name}" declares no authentication method \u2014 there is nothing to choose`
187
+ );
180
188
  }
181
189
  if (!provider.methods.includes(method)) {
182
- throw new TypeError(`o m\xE9todo "${method.label}" n\xE3o pertence ao provider "${provider.name}"`);
190
+ throw new TypeError(`method "${method.label}" does not belong to provider "${provider.name}"`);
183
191
  }
184
192
  if (method.type !== "oauth") {
185
- throw new TypeError(`o m\xE9todo "${method.label}" \xE9 de chave (api key), n\xE3o \xE9 um m\xE9todo de device \u2014 use o caminho de chave`);
193
+ throw new TypeError(
194
+ `method "${method.label}" is an api-key method, not a device method \u2014 use the api-key path`
195
+ );
186
196
  }
187
197
  const tokens = await method.authorize(comDefaults(opts.deps), hooks);
188
198
  const path = new AuthProvider(provider.oauth, store).persist(provider.name, tokens, opts.env);
189
- return tokens.accountId === void 0 ? {
190
- path
191
- } : {
192
- path,
193
- accountId: tokens.accountId
194
- };
199
+ return tokens.accountId === void 0 ? { path } : { path, accountId: tokens.accountId };
195
200
  }
196
- __name(loginWithDevice, "loginWithDevice");
197
201
  export {
198
202
  AuthProvider,
199
203
  CODEX_CLIENT_ID_ENV_VAR,
@@ -202,11 +206,15 @@ export {
202
206
  authFilePath2 as authFilePath,
203
207
  credentialHome,
204
208
  deviceLogin,
209
+ ensureFreshCredential2 as ensureFreshCredential,
210
+ extractAccountId,
205
211
  loginWithDevice,
206
212
  openaiDeviceLogin3 as openaiDeviceLogin,
213
+ persistOAuthTokens2 as persistOAuthTokens,
207
214
  pollDeviceToken,
208
215
  readAuthFile,
209
216
  readStoredOAuth2 as readStoredOAuth,
217
+ refreshOAuthTokens,
210
218
  requestDeviceCode,
211
219
  writeCredential
212
220
  };
package/dist/auth.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/auth/auth-provider.ts","../src/auth-entry.ts","../src/auth/device-provider.ts"],"mappings":"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","names":["authFilePath","ensureFreshCredential","openaiDeviceLogin","persistOAuthTokens","readStoredOAuth","withFileLock","RefreshFailure","Error","message","transitorio","name","MOTIVOS_TRANSITORIOS","classificarFalhaDeRefresh","err","texto","String","test","some","m","includes","esperaComJitter","tentativa","baseMs","aleatorio","Math","random","base","round","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","MAX_TENTATIVAS","falha","Promise","resolve","setTimeout","deviceLogin","deviceConfig","hooks","openaiDeviceLogin","persist","provider","tokens","persistOAuthTokens","authFilePath","CredentialError","credentialHome","readAuthFile","readStoredOAuth","writeCredential","deviceLogin","openaiDeviceLogin","pollDeviceToken","requestDeviceCode","openaiDeviceLogin","CODEX_CLIENT_ID","CODEX_ISSUER","CODEX_CLIENT_ID_ENV_VAR","CODEX_OAUTH","provider","clientId","process","env","authorizeEndpoint","tokenEndpoint","scopes","redirectUri","CODEX_DEVICE","deviceUsercodeEndpoint","devicePollEndpoint","verificationUri","CODEX_PROVIDER","Object","freeze","name","oauth","methods","label","type","authorize","deps","hooks","openaiDeviceLogin","comDefaults","fetch","sleep","ms","Promise","resolve","setTimeout","now","Date","loginWithDevice","method","store","opts","length","TypeError","includes","tokens","path","AuthProvider","persist","accountId","undefined"]}
1
+ {"version":3,"sources":["../src/auth/auth-provider.ts","../src/auth-entry.ts","../src/auth/device-provider.ts"],"mappings":"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","names":["authFilePath","readStoredOAuth","openaiDeviceLogin","ensureFreshCredential","persistOAuthTokens","openaiDeviceLogin","openaiDeviceLogin"]}