@theokit/sdk 5.9.0 → 5.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +100 -0
- package/dist/{agent-6STOEBGQ.js → agent-GZVZXKME.js} +18 -17
- package/dist/{agent-6STOEBGQ.js.map → agent-GZVZXKME.js.map} +1 -1
- package/dist/{agent-ZM4FDDL7.cjs → agent-WQ4LLTSY.cjs} +19 -18
- package/dist/{agent-ZM4FDDL7.cjs.map → agent-WQ4LLTSY.cjs.map} +1 -1
- package/dist/agent-session-store-ODD3IZCW.js +6 -0
- package/dist/{agent-session-store-AFML3AXC.js.map → agent-session-store-ODD3IZCW.js.map} +1 -1
- package/dist/agent-session-store-SVEJHSUA.cjs +23 -0
- package/dist/{agent-session-store-MTSIY3MH.cjs.map → agent-session-store-SVEJHSUA.cjs.map} +1 -1
- package/dist/auth/index.cjs +8 -7
- package/dist/auth/index.cjs.map +1 -1
- package/dist/auth/index.js +3 -2
- package/dist/auth/index.js.map +1 -1
- package/dist/{chunk-TC4RWP3Y.js → chunk-47Z6LP3I.js} +3 -3
- package/dist/{chunk-TC4RWP3Y.js.map → chunk-47Z6LP3I.js.map} +1 -1
- package/dist/{chunk-DDRX4LYS.js → chunk-7QJYKVP6.js} +3 -3
- package/dist/{chunk-DDRX4LYS.js.map → chunk-7QJYKVP6.js.map} +1 -1
- package/dist/{chunk-TTBIQTO5.cjs → chunk-DLUCTZ56.cjs} +15 -15
- package/dist/{chunk-TTBIQTO5.cjs.map → chunk-DLUCTZ56.cjs.map} +1 -1
- package/dist/chunk-EHD25JBZ.cjs +10 -0
- package/dist/chunk-EHD25JBZ.cjs.map +1 -0
- package/dist/{chunk-NOO6GZTZ.js → chunk-EVH3OUMY.js} +13 -12
- package/dist/chunk-EVH3OUMY.js.map +1 -0
- package/dist/{chunk-5522X223.js → chunk-EXI7EHDN.js} +4 -4
- package/dist/{chunk-5522X223.js.map → chunk-EXI7EHDN.js.map} +1 -1
- package/dist/{chunk-PSLCVSCS.cjs → chunk-FR6COQXZ.cjs} +6 -6
- package/dist/{chunk-PSLCVSCS.cjs.map → chunk-FR6COQXZ.cjs.map} +1 -1
- package/dist/{chunk-JOFVLOFY.js → chunk-FTZTZBCU.js} +12 -4
- package/dist/chunk-FTZTZBCU.js.map +1 -0
- package/dist/{chunk-HOHR75KF.js → chunk-HI3W37FY.js} +4 -3
- package/dist/chunk-HI3W37FY.js.map +1 -0
- package/dist/chunk-HU666T3Q.cjs +1891 -0
- package/dist/chunk-HU666T3Q.cjs.map +1 -0
- package/dist/{chunk-53RDNK3H.js → chunk-I2ORT6QD.js} +3 -3
- package/dist/{chunk-53RDNK3H.js.map → chunk-I2ORT6QD.js.map} +1 -1
- package/dist/{chunk-BM6PDJW3.cjs → chunk-JU76WCW7.cjs} +113 -112
- package/dist/chunk-JU76WCW7.cjs.map +1 -0
- package/dist/{chunk-J4SA2ZEJ.cjs → chunk-KIKKTW5O.cjs} +4 -4
- package/dist/{chunk-J4SA2ZEJ.cjs.map → chunk-KIKKTW5O.cjs.map} +1 -1
- package/dist/{chunk-5WR33BHA.cjs → chunk-KXKT3HSD.cjs} +4 -4
- package/dist/{chunk-5WR33BHA.cjs.map → chunk-KXKT3HSD.cjs.map} +1 -1
- package/dist/{chunk-UKBBYVNS.js → chunk-M2CCHC66.js} +3 -3
- package/dist/{chunk-UKBBYVNS.js.map → chunk-M2CCHC66.js.map} +1 -1
- package/dist/{chunk-OCEQ6DW2.cjs → chunk-N6OEX5TN.cjs} +2 -2
- package/dist/chunk-N6OEX5TN.cjs.map +1 -0
- package/dist/{chunk-QDQQYRJI.js → chunk-N7KYUNFO.js} +3 -3
- package/dist/{chunk-QDQQYRJI.js.map → chunk-N7KYUNFO.js.map} +1 -1
- package/dist/{chunk-7GDHFV2M.js → chunk-OPAKPEPG.js} +2 -2
- package/dist/chunk-OPAKPEPG.js.map +1 -0
- package/dist/{chunk-UNZOJVVC.js → chunk-OZLQ6ZFM.js} +3 -3
- package/dist/{chunk-UNZOJVVC.js.map → chunk-OZLQ6ZFM.js.map} +1 -1
- package/dist/{chunk-PYFBS6OQ.js → chunk-PEIV7LOU.js} +22 -21
- package/dist/chunk-PEIV7LOU.js.map +1 -0
- package/dist/chunk-Q7GYMXVC.js +8 -0
- package/dist/chunk-Q7GYMXVC.js.map +1 -0
- package/dist/{chunk-ARMFXTY6.cjs → chunk-QY3CIMUV.cjs} +34 -33
- package/dist/chunk-QY3CIMUV.cjs.map +1 -0
- package/dist/{chunk-B3XXQX6L.cjs → chunk-RX3CFWQ2.cjs} +6 -6
- package/dist/{chunk-B3XXQX6L.cjs.map → chunk-RX3CFWQ2.cjs.map} +1 -1
- package/dist/chunk-SGC7LSHF.cjs +18 -0
- package/dist/{chunk-R3ZQBPA5.cjs.map → chunk-SGC7LSHF.cjs.map} +1 -1
- package/dist/{chunk-RA7IE4NK.cjs → chunk-SKDNCTXG.cjs} +4 -3
- package/dist/chunk-SKDNCTXG.cjs.map +1 -0
- package/dist/chunk-SVCPJRUB.js +1874 -0
- package/dist/chunk-SVCPJRUB.js.map +1 -0
- package/dist/{chunk-EJROML3Q.js → chunk-TX56N7FR.js} +4 -3
- package/dist/chunk-TX56N7FR.js.map +1 -0
- package/dist/{chunk-76PIKR4P.cjs → chunk-VZ2JZ2EH.cjs} +5 -5
- package/dist/{chunk-76PIKR4P.cjs.map → chunk-VZ2JZ2EH.cjs.map} +1 -1
- package/dist/{chunk-T5KOSR5Y.cjs → chunk-X7Z2FEI7.cjs} +8 -8
- package/dist/{chunk-T5KOSR5Y.cjs.map → chunk-X7Z2FEI7.cjs.map} +1 -1
- package/dist/{chunk-2WXHA33T.js → chunk-XERM7PDQ.js} +3 -3
- package/dist/{chunk-2WXHA33T.js.map → chunk-XERM7PDQ.js.map} +1 -1
- package/dist/{chunk-KTA7YTZQ.cjs → chunk-XKZFIP7Z.cjs} +4 -4
- package/dist/{chunk-KTA7YTZQ.cjs.map → chunk-XKZFIP7Z.cjs.map} +1 -1
- package/dist/{chunk-MEUBLCM4.cjs → chunk-YEHQ3SIC.cjs} +4 -3
- package/dist/chunk-YEHQ3SIC.cjs.map +1 -0
- package/dist/{chunk-YIFFF23U.cjs → chunk-ZAM7BJXJ.cjs} +5 -5
- package/dist/{chunk-YIFFF23U.cjs.map → chunk-ZAM7BJXJ.cjs.map} +1 -1
- package/dist/{chunk-R2C3HXR3.js → chunk-ZDF2IJKC.js} +3 -3
- package/dist/{chunk-R2C3HXR3.js.map → chunk-ZDF2IJKC.js.map} +1 -1
- package/dist/{chunk-PQCTDMUI.js → chunk-ZHWKT2NI.js} +3 -3
- package/dist/{chunk-PQCTDMUI.js.map → chunk-ZHWKT2NI.js.map} +1 -1
- package/dist/{chunk-GZV6AVRL.cjs → chunk-ZWACQM5U.cjs} +11 -3
- package/dist/chunk-ZWACQM5U.cjs.map +1 -0
- package/dist/{compact-session-RBPLUPCK.cjs → compact-session-4QHBBGEY.cjs} +16 -15
- package/dist/{compact-session-RBPLUPCK.cjs.map → compact-session-4QHBBGEY.cjs.map} +1 -1
- package/dist/{compact-session-2N3ZYJTW.js → compact-session-PVAWTKKL.js} +7 -6
- package/dist/{compact-session-2N3ZYJTW.js.map → compact-session-PVAWTKKL.js.map} +1 -1
- package/dist/context/index.cjs +6 -6
- package/dist/context/index.js +3 -3
- package/dist/context-3FZRAO5K.js +7 -0
- package/dist/{context-SXR2HLHT.js.map → context-3FZRAO5K.js.map} +1 -1
- package/dist/{context-ZOULM2RB.cjs → context-B5J4GX2F.cjs} +7 -7
- package/dist/{context-ZOULM2RB.cjs.map → context-B5J4GX2F.cjs.map} +1 -1
- package/dist/cron.cjs +18 -17
- package/dist/cron.js +17 -16
- package/dist/eval.cjs +17 -16
- package/dist/eval.cjs.map +1 -1
- package/dist/eval.js +16 -15
- package/dist/eval.js.map +1 -1
- package/dist/fs-session-store-LCZBM3LT.js +10 -0
- package/dist/{fs-session-store-STZZFXH2.js.map → fs-session-store-LCZBM3LT.js.map} +1 -1
- package/dist/{fs-session-store-JHBJFKVV.cjs → fs-session-store-SVEMRE4K.cjs} +5 -5
- package/dist/{fs-session-store-JHBJFKVV.cjs.map → fs-session-store-SVEMRE4K.cjs.map} +1 -1
- package/dist/{index-manager-ONQJSWX5.js → index-manager-6B2UF5S3.js} +5 -5
- package/dist/{index-manager-ONQJSWX5.js.map → index-manager-6B2UF5S3.js.map} +1 -1
- package/dist/{index-manager-ZGJN25FD.cjs → index-manager-M3FHJCHQ.cjs} +6 -6
- package/dist/{index-manager-ZGJN25FD.cjs.map → index-manager-M3FHJCHQ.cjs.map} +1 -1
- package/dist/index.cjs +58 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -3
- package/dist/index.d.ts +30 -3
- package/dist/index.js +21 -20
- package/dist/index.js.map +1 -1
- package/dist/{inject-session-YNNOE3O6.js → inject-session-O24XGRR6.js} +5 -5
- package/dist/{inject-session-YNNOE3O6.js.map → inject-session-O24XGRR6.js.map} +1 -1
- package/dist/{inject-session-3FPXJDJP.cjs → inject-session-OMLFL2V3.cjs} +7 -7
- package/dist/{inject-session-3FPXJDJP.cjs.map → inject-session-OMLFL2V3.cjs.map} +1 -1
- package/dist/internal/memory/adapters/index.cjs +3 -2
- package/dist/internal/memory/adapters/index.js +2 -1
- package/dist/internal/memory/storage/index.cjs +32 -32
- package/dist/internal/memory/storage/index.js +3 -3
- package/dist/internal/persistence/persistence-schema.d.cts +1 -1
- package/dist/internal/persistence/persistence-schema.d.ts +1 -1
- package/dist/internal/providers/catalog-loader.d.ts +30 -3
- package/dist/internal/runtime/hooks/hooks-source.d.ts +24 -0
- package/dist/internal/runtime-fetch.d.ts +1 -0
- package/dist/models.cjs +12 -11
- package/dist/models.cjs.map +1 -1
- package/dist/models.js +4 -3
- package/dist/models.js.map +1 -1
- package/dist/persistence.cjs +7 -7
- package/dist/persistence.js +2 -2
- package/dist/providers.cjs +6 -5
- package/dist/providers.js +4 -3
- package/dist/{session-transcript-VTBTCGQX.js → session-transcript-AR7IBICT.js} +3 -3
- package/dist/{session-transcript-VTBTCGQX.js.map → session-transcript-AR7IBICT.js.map} +1 -1
- package/dist/{session-transcript-LGHSNVY5.cjs → session-transcript-RACG7BK2.cjs} +16 -16
- package/dist/{session-transcript-LGHSNVY5.cjs.map → session-transcript-RACG7BK2.cjs.map} +1 -1
- package/dist/subscription/index.cjs +2 -1
- package/dist/subscription/index.cjs.map +1 -1
- package/dist/subscription/index.js +2 -1
- package/dist/subscription/index.js.map +1 -1
- package/docs/error-codes.md +16 -16
- package/package.json +2 -2
- package/dist/agent-session-store-AFML3AXC.js +0 -6
- package/dist/agent-session-store-MTSIY3MH.cjs +0 -23
- package/dist/chunk-7GDHFV2M.js.map +0 -1
- package/dist/chunk-ARMFXTY6.cjs.map +0 -1
- package/dist/chunk-BM6PDJW3.cjs.map +0 -1
- package/dist/chunk-EJROML3Q.js.map +0 -1
- package/dist/chunk-GZV6AVRL.cjs.map +0 -1
- package/dist/chunk-HOHR75KF.js.map +0 -1
- package/dist/chunk-JOFVLOFY.js.map +0 -1
- package/dist/chunk-MEUBLCM4.cjs.map +0 -1
- package/dist/chunk-MFZODA5Y.js +0 -583
- package/dist/chunk-MFZODA5Y.js.map +0 -1
- package/dist/chunk-NOO6GZTZ.js.map +0 -1
- package/dist/chunk-OCEQ6DW2.cjs.map +0 -1
- package/dist/chunk-PYFBS6OQ.js.map +0 -1
- package/dist/chunk-R3ZQBPA5.cjs +0 -18
- package/dist/chunk-RA7IE4NK.cjs.map +0 -1
- package/dist/chunk-YRJA2POB.cjs +0 -601
- package/dist/chunk-YRJA2POB.cjs.map +0 -1
- package/dist/context-SXR2HLHT.js +0 -7
- package/dist/fs-session-store-STZZFXH2.js +0 -10
- package/dist/provider-catalog.json +0 -1295
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,105 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 5.9.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#713](https://github.com/usetheokit/theokit-sdk/pull/713) [`d1a0466`](https://github.com/usetheokit/theokit-sdk/commit/d1a0466257cebadbd4aaefee35e316091d641e22) Thanks [@usetheodev](https://github.com/usetheodev)! - A session transcript read on a runtime with no filesystem continues with an empty transcript instead
|
|
8
|
+
of failing the turn.
|
|
9
|
+
|
|
10
|
+
`readTranscript` treated only `ENOENT` as "there is no transcript yet" and rethrew everything else.
|
|
11
|
+
That is right for a real filesystem, where any other code is a genuine fault. On Workers there is no
|
|
12
|
+
filesystem at all, and `unenv`'s `createNotImplementedError` throws a plain `Error` carrying **no**
|
|
13
|
+
`code` — so the guard missed it and a turn died on a read whose only purpose is to recover history
|
|
14
|
+
that does not exist.
|
|
15
|
+
|
|
16
|
+
Measured on a deployed worker (theokit#705):
|
|
17
|
+
|
|
18
|
+
agent turn failed (SDK_ERROR): [unenv] fs.readFile is not implemented yet!
|
|
19
|
+
|
|
20
|
+
A codeless error inside a `try` that wraps only the `readFile` is a precise discriminator rather than
|
|
21
|
+
a catch-all: every real filesystem failure carries a code (`EACCES`, `EISDIR`, `EMFILE`), so nothing
|
|
22
|
+
that a filesystem can produce is swallowed by it. The absence of a code means the call never reached
|
|
23
|
+
a filesystem, which is the one case where an empty transcript is the correct answer. It is reported
|
|
24
|
+
through `diag`, so an operator who turns diagnostics on sees why the history is empty.
|
|
25
|
+
|
|
26
|
+
- [#713](https://github.com/usetheokit/theokit-sdk/pull/713) [`d1a0466`](https://github.com/usetheokit/theokit-sdk/commit/d1a0466257cebadbd4aaefee35e316091d641e22) Thanks [@usetheodev](https://github.com/usetheodev)! - `fetch` is bound to its receiver before it is stored or passed, so a provider transport works on
|
|
27
|
+
Cloudflare Workers.
|
|
28
|
+
|
|
29
|
+
Thirteen call sites across eleven files wrote `options.fetch ?? fetch`, which detaches the global
|
|
30
|
+
from its receiver. Node's undici tolerates that. workerd does not — calling the detached reference
|
|
31
|
+
as a property of another object, or as a bare function in a module where `this` is `undefined`,
|
|
32
|
+
throws `Illegal invocation: function called with incorrect this reference`.
|
|
33
|
+
|
|
34
|
+
Measured on a deployed worker while driving a real turn (theokit#705), and reached only after two
|
|
35
|
+
filesystem defects in this package were cleared, so it was the fourth layer of one deploy:
|
|
36
|
+
|
|
37
|
+
agent turn failed (AGENT_ERROR): openrouter transport failure on /v1/chat/completions:
|
|
38
|
+
Illegal invocation: function called with incorrect `this` reference.
|
|
39
|
+
|
|
40
|
+
The turn that failed went through `internal/llm/openai.ts`. Fixing only that one would have left
|
|
41
|
+
twelve identical landmines — every other provider, the memory adapter, the credential resolver, the
|
|
42
|
+
cloud-run client — each of them a deploy that fails on its first request. `internal/runtime-fetch.ts`
|
|
43
|
+
is now the one place that knows the rule: `boundFetch(override?)` returns an injected fetch
|
|
44
|
+
untouched, so a test double still reaches the transport as itself, and otherwise returns
|
|
45
|
+
`globalThis.fetch.bind(globalThis)`.
|
|
46
|
+
|
|
47
|
+
Binding where the reference is taken, rather than a `(0, f)(…)` at each invocation, fixes every call
|
|
48
|
+
that reference will ever receive and gives the sweep in `tests/runtime/fetch-is-bound.test.ts`
|
|
49
|
+
something it can assert: no source file under `src/` takes a detached reference to the global.
|
|
50
|
+
|
|
51
|
+
- [#713](https://github.com/usetheokit/theokit-sdk/pull/713) [`4f2c22c`](https://github.com/usetheokit/theokit-sdk/commit/4f2c22c9e86cdc07f0a6ccf5b0b00ef97587b709) Thanks [@usetheodev](https://github.com/usetheodev)! - The provider catalog is embedded at build time instead of read from disk, so the SDK runs on a
|
|
52
|
+
runtime with no filesystem.
|
|
53
|
+
|
|
54
|
+
`loadProviderCatalog` read `provider-catalog.json` with `readFileSync`, from a directory computed as
|
|
55
|
+
`dirname(fileURLToPath(import.meta.url))` at module scope. Both halves break on Cloudflare Workers,
|
|
56
|
+
Vercel Functions and any bundled deployment — and the catalog is only model METADATA, so an
|
|
57
|
+
environment that could not read it could not run a turn at all.
|
|
58
|
+
|
|
59
|
+
Measured end to end while deploying a TheoKit app (theokit#705). Cloudflare executes the top-level
|
|
60
|
+
module during validation, so the upload was refused before any request existed with
|
|
61
|
+
`The "path" argument must be of type string … Received undefined` (code 10021). With
|
|
62
|
+
`import.meta.url` substituted by the consumer's bundler the module initialised and the turn failed
|
|
63
|
+
with `[unenv] fs.readFileSync is not implemented yet!`; with a newer `compatibility_date` that became
|
|
64
|
+
the honest `ENOENT: readAll '/provider-catalog.json'`. The same `ENOENT` reached a deployed Vercel
|
|
65
|
+
function, whose bundle carries the JS and not the JSON.
|
|
66
|
+
|
|
67
|
+
No consumer's bundler could fix it from outside. Probed from inside a deployed worker, workerd's
|
|
68
|
+
whole virtual filesystem is `/bundle/worker.js`, an empty `/tmp` and `/dev` — there is nowhere to
|
|
69
|
+
place this package's private data file such that `join(dirname(<a file URL>), …)` finds it, short of
|
|
70
|
+
hardcoding our internal layout into their build.
|
|
71
|
+
|
|
72
|
+
The import uses `with { type: "json" }`, following `internal/budget/pricing-registry.ts`, which has
|
|
73
|
+
imported a sibling JSON that way in this package for as long as it has existed. Bundlers inline it,
|
|
74
|
+
so the emitted module carries the data and reaches for nothing. The build no longer copies the JSON
|
|
75
|
+
into `dist`, because nothing reads it there.
|
|
76
|
+
|
|
77
|
+
## 5.9.1
|
|
78
|
+
|
|
79
|
+
### Patch Changes
|
|
80
|
+
|
|
81
|
+
- [#694](https://github.com/usetheokit/theokit-sdk/pull/694) [`aa2a04a`](https://github.com/usetheokit/theokit-sdk/commit/aa2a04a1c08514b0ea47d779640fc37f119cd21b) Thanks [@usetheodev](https://github.com/usetheodev)! - The README documents the shape of `.theokit/hooks.json`, which it previously told a consumer to
|
|
82
|
+
validate against and did not show. The sentence *"read and validated here, against the shape above"*
|
|
83
|
+
had no shape above it — the section stated where the file is read from and never what goes in it, so
|
|
84
|
+
the one thing a consumer needs in order to exercise the gate that guards it was missing
|
|
85
|
+
(usetheokit/theokit-sdk#638).
|
|
86
|
+
|
|
87
|
+
What is documented is read from the loader rather than restated beside it: the JSON shape, the three
|
|
88
|
+
fields a hook entry may carry (`type`, `command`, `timeout`), the seven Claude Code fields refused
|
|
89
|
+
with a named error rather than dropped, the four events that actually fire, and the nested
|
|
90
|
+
`hookSpecificOutput.permissionDecision` deny shape with `ask` projecting to deny.
|
|
91
|
+
|
|
92
|
+
`tests/the-readme-hooks-shape-matches-the-loader.test.ts` holds it there, reading
|
|
93
|
+
`CLAUDE_CODE_EVENT_MAP`, `ACCEPTED_HOOK_FIELDS` and `UNIMPLEMENTED_CLAUDE_CODE_HOOK_FIELDS` from the
|
|
94
|
+
loader — the last two newly exported for that purpose, from a module that is already `@internal`, on
|
|
95
|
+
the precedent `CLAUDE_CODE_EVENT_MAP` set when it was exported so the supported set would be derived
|
|
96
|
+
rather than asserted.
|
|
97
|
+
|
|
98
|
+
Each list is read from its own sentence rather than from the section. The first version of the test
|
|
99
|
+
asserted the section contained `` `if` `` and passed after `if` was deleted from the refused list,
|
|
100
|
+
because the next sentence happens to mention it — a green assertion for a reason unrelated to its
|
|
101
|
+
claim, which is the same defect one level up.
|
|
102
|
+
|
|
3
103
|
## 5.9.0
|
|
4
104
|
|
|
5
105
|
### Minor Changes
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
export { Agent } from './chunk-
|
|
1
|
+
export { Agent } from './chunk-PEIV7LOU.js';
|
|
2
2
|
import './chunk-XKMVJ443.js';
|
|
3
|
-
import './chunk-
|
|
3
|
+
import './chunk-EXI7EHDN.js';
|
|
4
4
|
import './chunk-K2BQQ445.js';
|
|
5
|
-
import './chunk-
|
|
6
|
-
import './chunk-
|
|
5
|
+
import './chunk-ZDF2IJKC.js';
|
|
6
|
+
import './chunk-ZHWKT2NI.js';
|
|
7
7
|
import './chunk-2SFBB54R.js';
|
|
8
|
-
import './chunk-
|
|
8
|
+
import './chunk-HI3W37FY.js';
|
|
9
9
|
import './chunk-H73MEMQB.js';
|
|
10
10
|
import './chunk-OR6XIWLB.js';
|
|
11
|
-
import './chunk-
|
|
12
|
-
import './chunk-
|
|
13
|
-
import './chunk-
|
|
11
|
+
import './chunk-47Z6LP3I.js';
|
|
12
|
+
import './chunk-OZLQ6ZFM.js';
|
|
13
|
+
import './chunk-EVH3OUMY.js';
|
|
14
14
|
import './chunk-SUVCHX4L.js';
|
|
15
15
|
import './chunk-2XC6KDJM.js';
|
|
16
16
|
import './chunk-TE6XVTOA.js';
|
|
17
17
|
import './chunk-24MGQDK3.js';
|
|
18
|
-
import './chunk-
|
|
18
|
+
import './chunk-XERM7PDQ.js';
|
|
19
19
|
import './chunk-HKCKOAIO.js';
|
|
20
|
-
import './chunk-
|
|
21
|
-
import './chunk-
|
|
20
|
+
import './chunk-7QJYKVP6.js';
|
|
21
|
+
import './chunk-OPAKPEPG.js';
|
|
22
22
|
import './chunk-KVNWIAO4.js';
|
|
23
23
|
import './chunk-SVQIW5RJ.js';
|
|
24
24
|
import './chunk-FD2UT76F.js';
|
|
@@ -35,7 +35,7 @@ import './chunk-UKMBRMGT.js';
|
|
|
35
35
|
import './chunk-7JAKO3NM.js';
|
|
36
36
|
import './chunk-ZWFTECOE.js';
|
|
37
37
|
import './chunk-GTX6FEDP.js';
|
|
38
|
-
import './chunk-
|
|
38
|
+
import './chunk-FTZTZBCU.js';
|
|
39
39
|
import './chunk-WE22OXQA.js';
|
|
40
40
|
import './chunk-XZHJYSPB.js';
|
|
41
41
|
import './chunk-BKMDRBJ7.js';
|
|
@@ -47,13 +47,14 @@ import './chunk-X7EUUHXU.js';
|
|
|
47
47
|
import './chunk-MQGSOKR3.js';
|
|
48
48
|
import './chunk-GMRFAX4I.js';
|
|
49
49
|
import './chunk-R7WIIPUR.js';
|
|
50
|
-
import './chunk-
|
|
51
|
-
import './chunk-
|
|
50
|
+
import './chunk-I2ORT6QD.js';
|
|
51
|
+
import './chunk-SVCPJRUB.js';
|
|
52
52
|
import './chunk-AGACYRJ2.js';
|
|
53
|
-
import './chunk-
|
|
53
|
+
import './chunk-TX56N7FR.js';
|
|
54
54
|
import './chunk-5Q4RTLMP.js';
|
|
55
55
|
import './chunk-H3CVJSFC.js';
|
|
56
|
+
import './chunk-Q7GYMXVC.js';
|
|
56
57
|
import './chunk-B5MHRQJZ.js';
|
|
57
58
|
import './chunk-CZJ6Q7CW.js';
|
|
58
|
-
//# sourceMappingURL=agent-
|
|
59
|
-
//# sourceMappingURL=agent-
|
|
59
|
+
//# sourceMappingURL=agent-GZVZXKME.js.map
|
|
60
|
+
//# sourceMappingURL=agent-GZVZXKME.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"agent-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"agent-GZVZXKME.js"}
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkJU76WCW7_cjs = require('./chunk-JU76WCW7.cjs');
|
|
4
4
|
require('./chunk-J6GXS5A2.cjs');
|
|
5
|
-
require('./chunk-
|
|
5
|
+
require('./chunk-FR6COQXZ.cjs');
|
|
6
6
|
require('./chunk-BUUUWQMB.cjs');
|
|
7
|
-
require('./chunk-
|
|
8
|
-
require('./chunk-
|
|
7
|
+
require('./chunk-DLUCTZ56.cjs');
|
|
8
|
+
require('./chunk-KIKKTW5O.cjs');
|
|
9
9
|
require('./chunk-BV2MWEMV.cjs');
|
|
10
|
-
require('./chunk-
|
|
10
|
+
require('./chunk-YEHQ3SIC.cjs');
|
|
11
11
|
require('./chunk-GHX4P3V2.cjs');
|
|
12
12
|
require('./chunk-TMKTSYDS.cjs');
|
|
13
|
-
require('./chunk-
|
|
14
|
-
require('./chunk-
|
|
15
|
-
require('./chunk-
|
|
13
|
+
require('./chunk-VZ2JZ2EH.cjs');
|
|
14
|
+
require('./chunk-RX3CFWQ2.cjs');
|
|
15
|
+
require('./chunk-QY3CIMUV.cjs');
|
|
16
16
|
require('./chunk-CQYBJOB2.cjs');
|
|
17
17
|
require('./chunk-YJNYDJ2T.cjs');
|
|
18
18
|
require('./chunk-WPO3VCY4.cjs');
|
|
19
19
|
require('./chunk-QOGNZMHD.cjs');
|
|
20
|
-
require('./chunk-
|
|
20
|
+
require('./chunk-ZAM7BJXJ.cjs');
|
|
21
21
|
require('./chunk-2ZPEDVLM.cjs');
|
|
22
|
-
require('./chunk-
|
|
23
|
-
require('./chunk-
|
|
22
|
+
require('./chunk-XKZFIP7Z.cjs');
|
|
23
|
+
require('./chunk-N6OEX5TN.cjs');
|
|
24
24
|
require('./chunk-KRD3GQAA.cjs');
|
|
25
25
|
require('./chunk-RQMCOFAI.cjs');
|
|
26
26
|
require('./chunk-MUUQ2WFJ.cjs');
|
|
@@ -37,7 +37,7 @@ require('./chunk-SA6K24NB.cjs');
|
|
|
37
37
|
require('./chunk-IIYJMXYW.cjs');
|
|
38
38
|
require('./chunk-NJSIAJEK.cjs');
|
|
39
39
|
require('./chunk-NKIQTLFA.cjs');
|
|
40
|
-
require('./chunk-
|
|
40
|
+
require('./chunk-ZWACQM5U.cjs');
|
|
41
41
|
require('./chunk-A4RAL2ER.cjs');
|
|
42
42
|
require('./chunk-P22BZE7G.cjs');
|
|
43
43
|
require('./chunk-OF2CLCTH.cjs');
|
|
@@ -49,12 +49,13 @@ require('./chunk-TY56BKSK.cjs');
|
|
|
49
49
|
require('./chunk-MPR2ISL2.cjs');
|
|
50
50
|
require('./chunk-J5623RIV.cjs');
|
|
51
51
|
require('./chunk-3EE6LVWT.cjs');
|
|
52
|
-
require('./chunk-
|
|
53
|
-
require('./chunk-
|
|
52
|
+
require('./chunk-SGC7LSHF.cjs');
|
|
53
|
+
require('./chunk-HU666T3Q.cjs');
|
|
54
54
|
require('./chunk-NVXXWAU7.cjs');
|
|
55
|
-
require('./chunk-
|
|
55
|
+
require('./chunk-SKDNCTXG.cjs');
|
|
56
56
|
require('./chunk-NAGPKWOD.cjs');
|
|
57
57
|
require('./chunk-OLSEWLK5.cjs');
|
|
58
|
+
require('./chunk-EHD25JBZ.cjs');
|
|
58
59
|
require('./chunk-UNFBHV46.cjs');
|
|
59
60
|
require('./chunk-6LHQPOMI.cjs');
|
|
60
61
|
|
|
@@ -62,7 +63,7 @@ require('./chunk-6LHQPOMI.cjs');
|
|
|
62
63
|
|
|
63
64
|
Object.defineProperty(exports, "Agent", {
|
|
64
65
|
enumerable: true,
|
|
65
|
-
get: function () { return
|
|
66
|
+
get: function () { return chunkJU76WCW7_cjs.Agent; }
|
|
66
67
|
});
|
|
67
|
-
//# sourceMappingURL=agent-
|
|
68
|
-
//# sourceMappingURL=agent-
|
|
68
|
+
//# sourceMappingURL=agent-WQ4LLTSY.cjs.map
|
|
69
|
+
//# sourceMappingURL=agent-WQ4LLTSY.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"agent-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"agent-WQ4LLTSY.cjs"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { appendCompactBoundaryRecord, persistTurn, readSessionMessages } from './chunk-XERM7PDQ.js';
|
|
2
|
+
import './chunk-FTZTZBCU.js';
|
|
3
|
+
import './chunk-3JHIFQ4I.js';
|
|
4
|
+
import './chunk-CZJ6Q7CW.js';
|
|
5
|
+
//# sourceMappingURL=agent-session-store-ODD3IZCW.js.map
|
|
6
|
+
//# sourceMappingURL=agent-session-store-ODD3IZCW.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"agent-session-store-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"agent-session-store-ODD3IZCW.js"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkZAM7BJXJ_cjs = require('./chunk-ZAM7BJXJ.cjs');
|
|
4
|
+
require('./chunk-ZWACQM5U.cjs');
|
|
5
|
+
require('./chunk-JLRLCBJ4.cjs');
|
|
6
|
+
require('./chunk-6LHQPOMI.cjs');
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
Object.defineProperty(exports, "appendCompactBoundaryRecord", {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
get: function () { return chunkZAM7BJXJ_cjs.appendCompactBoundaryRecord; }
|
|
13
|
+
});
|
|
14
|
+
Object.defineProperty(exports, "persistTurn", {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: function () { return chunkZAM7BJXJ_cjs.persistTurn; }
|
|
17
|
+
});
|
|
18
|
+
Object.defineProperty(exports, "readSessionMessages", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () { return chunkZAM7BJXJ_cjs.readSessionMessages; }
|
|
21
|
+
});
|
|
22
|
+
//# sourceMappingURL=agent-session-store-SVEJHSUA.cjs.map
|
|
23
|
+
//# sourceMappingURL=agent-session-store-SVEJHSUA.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"agent-session-store-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"agent-session-store-SVEJHSUA.cjs"}
|
package/dist/auth/index.cjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunkFRITRLZQ_cjs = require('../chunk-FRITRLZQ.cjs');
|
|
4
|
-
var
|
|
4
|
+
var chunkSKDNCTXG_cjs = require('../chunk-SKDNCTXG.cjs');
|
|
5
5
|
var chunkNAGPKWOD_cjs = require('../chunk-NAGPKWOD.cjs');
|
|
6
6
|
var chunkOLSEWLK5_cjs = require('../chunk-OLSEWLK5.cjs');
|
|
7
|
+
require('../chunk-EHD25JBZ.cjs');
|
|
7
8
|
require('../chunk-UNFBHV46.cjs');
|
|
8
9
|
require('../chunk-6LHQPOMI.cjs');
|
|
9
10
|
|
|
@@ -201,7 +202,7 @@ async function openaiDeviceLogin(config, deps, hooks) {
|
|
|
201
202
|
"device poll returned no authorization_code"
|
|
202
203
|
);
|
|
203
204
|
}
|
|
204
|
-
const tokens = await
|
|
205
|
+
const tokens = await chunkSKDNCTXG_cjs.exchangeCode(
|
|
205
206
|
config,
|
|
206
207
|
{ code: data.authorization_code, verifier: data.code_verifier },
|
|
207
208
|
deps
|
|
@@ -249,23 +250,23 @@ Object.defineProperty(exports, "providerFromApiKeyPrefix", {
|
|
|
249
250
|
});
|
|
250
251
|
Object.defineProperty(exports, "ensureFreshCredential", {
|
|
251
252
|
enumerable: true,
|
|
252
|
-
get: function () { return
|
|
253
|
+
get: function () { return chunkSKDNCTXG_cjs.ensureFreshCredential; }
|
|
253
254
|
});
|
|
254
255
|
Object.defineProperty(exports, "exchangeCode", {
|
|
255
256
|
enumerable: true,
|
|
256
|
-
get: function () { return
|
|
257
|
+
get: function () { return chunkSKDNCTXG_cjs.exchangeCode; }
|
|
257
258
|
});
|
|
258
259
|
Object.defineProperty(exports, "persistOAuthTokens", {
|
|
259
260
|
enumerable: true,
|
|
260
|
-
get: function () { return
|
|
261
|
+
get: function () { return chunkSKDNCTXG_cjs.persistOAuthTokens; }
|
|
261
262
|
});
|
|
262
263
|
Object.defineProperty(exports, "refreshOAuthTokens", {
|
|
263
264
|
enumerable: true,
|
|
264
|
-
get: function () { return
|
|
265
|
+
get: function () { return chunkSKDNCTXG_cjs.refreshOAuthTokens; }
|
|
265
266
|
});
|
|
266
267
|
Object.defineProperty(exports, "resolveCredential", {
|
|
267
268
|
enumerable: true,
|
|
268
|
-
get: function () { return
|
|
269
|
+
get: function () { return chunkSKDNCTXG_cjs.resolveCredential; }
|
|
269
270
|
});
|
|
270
271
|
Object.defineProperty(exports, "CredentialError", {
|
|
271
272
|
enumerable: true,
|
package/dist/auth/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/internal/auth/oauth-device.ts"],"names":["AuthCallbackError","exchangeCode"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * M42 — the SDK OAuth device-authorization flows (RFC 8628 + OpenAI two-step headless). Split out of\n * oauth-engine.ts to respect the 500-line file budget; a sibling of the core engine. Promoted DOWN from\n * agent-builder's hardened `agents/lib/oauth-device.ts` (M37).\n *\n * Implements two device flows against their published specs: the RFC 8628 device-grant poll loop\n * (device_code → authorization_pending / slow_down) and OpenAI's two-step headless flow, including the\n * JWT-claim / account-id extraction used to attribute an account.\n * Design choices: network I/O + clock + sleep are INJECTED (deterministic tests), failures raise the SDK's\n * typed `AuthCallbackError`, and a device-code expiry DEADLINE guards each poll loop.\n *\n * @internal\n */\nimport { AuthCallbackError } from \"../../server/auth/errors.js\";\nimport { exchangeCode } from \"./oauth-engine.js\";\nimport type {\n DeviceCodeGrant,\n DeviceDeps,\n DeviceOAuthConfig,\n OAuthTokens,\n OpenAIDeviceConfig,\n} from \"./types.js\";\n\n// ─── OAuth 2.0 Device Authorization Grant (RFC 8628) — terminal-first / headless login ───\n\n/** Buffer added to every poll interval to avoid hitting the server a hair early. */\nconst POLLING_SAFETY_MARGIN_MS = 3000;\n\n/**\n * Parse a JSON body, or fail with this module's typed error instead of a raw `SyntaxError`.\n *\n * Every failure in this file is supposed to reach the caller as an `AuthCallbackError` carrying a code\n * the CLI can branch on. `res.json()` breaks that contract: a device endpoint that answers with HTML —\n * a captive portal, a corporate proxy's sign-in page, a load balancer's error page — makes it reject\n * with a `SyntaxError` that no `catch` here handles, so it escapes untyped past a caller prepared only\n * for `AuthCallbackError`.\n *\n * The body is quoted, truncated, because \"not JSON\" and \"not JSON, and it looks like a proxy login\n * page\" are different diagnoses for whoever is holding the terminal — and routing them to the provider\n * when the fault is their network is the expensive kind of wrong.\n */\nasync function parseJsonOrFail(res: Response, code: string, what: string): Promise<unknown> {\n const text = await res.text().catch(() => \"\");\n try {\n return JSON.parse(text);\n } catch {\n throw new AuthCallbackError(code, `${what} returned a non-JSON body: ${text.slice(0, 120)}`);\n }\n}\n\n/** Step 1 — request a device code. POSTs `{client_id, scope}` to the device endpoint. */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: RFC 8628 device-code request — cohesive network response parser ported verbatim (ADR D3).\nexport async function requestDeviceCode(\n config: DeviceOAuthConfig,\n deps: Pick<DeviceDeps, \"fetch\">,\n): Promise<DeviceCodeGrant> {\n let res: Response;\n try {\n res = await deps.fetch(config.deviceCodeEndpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\", accept: \"application/json\" },\n body: new URLSearchParams({\n client_id: config.clientId,\n scope: config.scopes.join(\" \"),\n }).toString(),\n });\n } catch (err) {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n `device request failed: ${(err as Error).message}`,\n );\n }\n if (!res.ok) {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n `device endpoint returned HTTP ${res.status}`,\n );\n }\n const data = (await parseJsonOrFail(\n res,\n \"oauth_device_authorization_failed\",\n \"device endpoint\",\n )) as {\n device_code?: unknown;\n user_code?: unknown;\n verification_uri?: unknown;\n verification_uri_complete?: unknown;\n interval?: unknown;\n expires_in?: unknown;\n };\n if (typeof data.device_code !== \"string\" || typeof data.user_code !== \"string\") {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n \"device response missing device_code/user_code\",\n );\n }\n const verification =\n typeof data.verification_uri === \"string\"\n ? data.verification_uri\n : typeof data.verification_uri_complete === \"string\"\n ? data.verification_uri_complete\n : \"\";\n return {\n deviceCode: data.device_code,\n userCode: data.user_code,\n verificationUri: verification,\n interval: typeof data.interval === \"number\" && data.interval > 0 ? data.interval : 5,\n expiresIn: typeof data.expires_in === \"number\" && data.expires_in > 0 ? data.expires_in : 900,\n };\n}\n\n/**\n * Step 2 — poll the token endpoint until the user approves (or the code expires). Handles RFC 8628\n * `authorization_pending` (keep waiting) and `slow_down` (back off), with an expiry deadline so it cannot\n * spin forever.\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: RFC 8628 poll state machine (authorization_pending / slow_down / success / expiry) — a cohesive loop ported verbatim (ADR D3); fragmenting it would obscure the protocol.\nexport async function pollDeviceToken(\n config: DeviceOAuthConfig,\n grant: DeviceCodeGrant,\n deps: DeviceDeps,\n): Promise<OAuthTokens> {\n const deadline = deps.now() + grant.expiresIn * 1000;\n let intervalMs = grant.interval * 1000;\n\n while (deps.now() < deadline) {\n let res: Response;\n try {\n res = await deps.fetch(config.tokenEndpoint, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/x-www-form-urlencoded\",\n accept: \"application/json\",\n },\n body: new URLSearchParams({\n client_id: config.clientId,\n device_code: grant.deviceCode,\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n }).toString(),\n });\n } catch (err) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `device token poll failed: ${(err as Error).message}`,\n );\n }\n // RFC 8628 §3.5: `authorization_pending` / `slow_down` arrive as a 400 with an `error` body — so the\n // body MUST be read before deciding failure. Parse first; only a non-OAuth-shaped body on a non-2xx fails.\n const data = (await res.json().catch(() => ({}))) as {\n access_token?: string;\n refresh_token?: string;\n expires_in?: number;\n id_token?: string;\n error?: string;\n interval?: number;\n };\n if (!res.ok && typeof data.error !== \"string\") {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `device token endpoint returned HTTP ${res.status}`,\n );\n }\n\n if (typeof data.access_token === \"string\" && data.access_token.length > 0) {\n const expiresIn = typeof data.expires_in === \"number\" ? data.expires_in : 0;\n const accountId = extractAccountId({\n access_token: data.access_token,\n id_token: data.id_token,\n });\n return {\n access: data.access_token,\n // Some device-grant providers (e.g. GitHub) issue no separate refresh token — reuse the access\n // token as the refresh handle.\n refresh: data.refresh_token ?? data.access_token,\n expires: deps.now() + expiresIn * 1000,\n ...(accountId !== undefined ? { accountId } : {}),\n };\n }\n\n if (data.error === \"authorization_pending\") {\n await deps.sleep(intervalMs + POLLING_SAFETY_MARGIN_MS);\n continue;\n }\n if (data.error === \"slow_down\") {\n // RFC 8628 §3.5: add 5s to the interval, or honor a server-provided one.\n intervalMs =\n (typeof data.interval === \"number\" && data.interval > 0\n ? data.interval\n : grant.interval + 5) * 1000;\n await deps.sleep(intervalMs + POLLING_SAFETY_MARGIN_MS);\n continue;\n }\n if (typeof data.error === \"string\") {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `device authorization rejected: ${data.error}`,\n );\n }\n await deps.sleep(intervalMs + POLLING_SAFETY_MARGIN_MS);\n }\n throw new AuthCallbackError(\n \"oauth_device_code_expired\",\n \"the device code expired before it was approved\",\n );\n}\n\n/**\n * The full device login: request a code, hand the user the verification URL + user code via `onPrompt`\n * (never printed here — the caller renders it, keeping this module output-free), then poll to completion.\n */\nexport async function deviceLogin(\n config: DeviceOAuthConfig,\n deps: DeviceDeps,\n hooks: {\n onPrompt: (p: { userCode: string; verificationUri: string; expiresIn: number }) => void;\n },\n): Promise<OAuthTokens> {\n const grant = await requestDeviceCode(config, deps);\n hooks.onPrompt({\n userCode: grant.userCode,\n verificationUri: grant.verificationUri,\n expiresIn: grant.expiresIn,\n });\n return pollDeviceToken(config, grant, deps);\n}\n\n// ─── OpenAI / ChatGPT \"headless\" device flow (two-step) ───\n\n/** Step 1 (OpenAI) — request the user code. */\nexport async function requestOpenAIUsercode(\n config: OpenAIDeviceConfig,\n deps: Pick<DeviceDeps, \"fetch\">,\n): Promise<{ deviceAuthId: string; userCode: string; interval: number }> {\n let res: Response;\n try {\n res = await deps.fetch(config.deviceUsercodeEndpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", accept: \"application/json\" },\n body: JSON.stringify({ client_id: config.clientId }),\n });\n } catch (err) {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n `usercode request failed: ${(err as Error).message}`,\n );\n }\n if (!res.ok) {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n `usercode endpoint returned HTTP ${res.status}`,\n );\n }\n const data = (await parseJsonOrFail(\n res,\n \"oauth_device_authorization_failed\",\n \"usercode endpoint\",\n )) as {\n device_auth_id?: unknown;\n user_code?: unknown;\n interval?: unknown;\n };\n if (typeof data.device_auth_id !== \"string\" || typeof data.user_code !== \"string\") {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n \"usercode response missing device_auth_id/user_code\",\n );\n }\n const interval = Math.max(\n typeof data.interval === \"string\" ? parseInt(data.interval, 10) || 5 : 5,\n 1,\n );\n return { deviceAuthId: data.device_auth_id, userCode: data.user_code, interval };\n}\n\n/**\n * Step 2+3 (OpenAI) — poll for the authorization code (200 = ready; 403/404 = pending; else fail), then\n * exchange it for tokens at the standard `/oauth/token` endpoint (reuses `exchangeCode`).\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: OpenAI two-step headless poll loop (200 ready / 403,404 pending / else fail) — cohesive network state machine ported verbatim (ADR D3).\nexport async function openaiDeviceLogin(\n config: OpenAIDeviceConfig,\n deps: DeviceDeps,\n hooks: { onPrompt: (p: { userCode: string; verificationUri: string }) => void },\n): Promise<OAuthTokens> {\n const { deviceAuthId, userCode, interval } = await requestOpenAIUsercode(config, deps);\n hooks.onPrompt({ userCode, verificationUri: config.verificationUri });\n\n const intervalMs = interval * 1000;\n // Bound the loop so it cannot spin forever if the provider never resolves (upstream loops unbounded).\n const deadline = deps.now() + 15 * 60 * 1000;\n while (deps.now() < deadline) {\n let res: Response;\n try {\n res = await deps.fetch(config.devicePollEndpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", accept: \"application/json\" },\n body: JSON.stringify({ device_auth_id: deviceAuthId, user_code: userCode }),\n });\n } catch (err) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `device poll failed: ${(err as Error).message}`,\n );\n }\n if (res.ok) {\n const data = (await parseJsonOrFail(res, \"oauth_token_exchange_failed\", \"device poll\")) as {\n authorization_code?: unknown;\n code_verifier?: unknown;\n };\n if (typeof data.authorization_code !== \"string\" || typeof data.code_verifier !== \"string\") {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n \"device poll returned no authorization_code\",\n );\n }\n const tokens = await exchangeCode(\n config,\n { code: data.authorization_code, verifier: data.code_verifier },\n deps,\n );\n // M43 D4 fix #2 — the two-step exchange returns a JWT access token but `parseTokenResponse` only reads a\n // top-level `account_id`. JWT-extract the `chatgpt_account_id` (as the generic device poll already does)\n // so the login persists a non-empty account_id for the Codex `ChatGPT-Account-Id` header.\n return {\n ...tokens,\n accountId: tokens.accountId ?? extractAccountId({ access_token: tokens.access }),\n };\n }\n // 403/404 = still pending (user has not approved yet); anything else is a hard failure.\n if (res.status !== 403 && res.status !== 404) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `device poll returned HTTP ${res.status}`,\n );\n }\n await deps.sleep(intervalMs + POLLING_SAFETY_MARGIN_MS);\n }\n throw new AuthCallbackError(\n \"oauth_device_code_expired\",\n \"the device authorization expired before approval\",\n );\n}\n\n/** JWT id/access-token claims we read to attribute an account. */\ninterface IdTokenClaims {\n chatgpt_account_id?: string;\n organizations?: Array<{ id: string }>;\n \"https://api.openai.com/auth\"?: { chatgpt_account_id?: string };\n}\n\n/** Decode a JWT's claim set (no signature verification — used only to read a self-reported account id). */\nexport function parseJwtClaims(token: string): IdTokenClaims | undefined {\n const parts = token.split(\".\");\n if (parts.length !== 3) return undefined;\n try {\n return JSON.parse(Buffer.from(parts[1] as string, \"base64url\").toString()) as IdTokenClaims;\n } catch {\n return undefined;\n }\n}\n\n/** Best-effort account id from an id/access token's claims (OpenAI/ChatGPT shape). */\nexport function extractAccountId(tokens: {\n id_token?: string;\n access_token?: string;\n}): string | undefined {\n for (const token of [tokens.id_token, tokens.access_token]) {\n if (token === undefined) continue;\n const claims = parseJwtClaims(token);\n const id =\n claims?.chatgpt_account_id ??\n claims?.[\"https://api.openai.com/auth\"]?.chatgpt_account_id ??\n claims?.organizations?.[0]?.id;\n if (id !== undefined) return id;\n }\n return undefined;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/internal/auth/oauth-device.ts"],"names":["AuthCallbackError","exchangeCode"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * M42 — the SDK OAuth device-authorization flows (RFC 8628 + OpenAI two-step headless). Split out of\n * oauth-engine.ts to respect the 500-line file budget; a sibling of the core engine. Promoted DOWN from\n * agent-builder's hardened `agents/lib/oauth-device.ts` (M37).\n *\n * Implements two device flows against their published specs: the RFC 8628 device-grant poll loop\n * (device_code → authorization_pending / slow_down) and OpenAI's two-step headless flow, including the\n * JWT-claim / account-id extraction used to attribute an account.\n * Design choices: network I/O + clock + sleep are INJECTED (deterministic tests), failures raise the SDK's\n * typed `AuthCallbackError`, and a device-code expiry DEADLINE guards each poll loop.\n *\n * @internal\n */\nimport { AuthCallbackError } from \"../../server/auth/errors.js\";\nimport { exchangeCode } from \"./oauth-engine.js\";\nimport type {\n DeviceCodeGrant,\n DeviceDeps,\n DeviceOAuthConfig,\n OAuthTokens,\n OpenAIDeviceConfig,\n} from \"./types.js\";\n\n// ─── OAuth 2.0 Device Authorization Grant (RFC 8628) — terminal-first / headless login ───\n\n/** Buffer added to every poll interval to avoid hitting the server a hair early. */\nconst POLLING_SAFETY_MARGIN_MS = 3000;\n\n/**\n * Parse a JSON body, or fail with this module's typed error instead of a raw `SyntaxError`.\n *\n * Every failure in this file is supposed to reach the caller as an `AuthCallbackError` carrying a code\n * the CLI can branch on. `res.json()` breaks that contract: a device endpoint that answers with HTML —\n * a captive portal, a corporate proxy's sign-in page, a load balancer's error page — makes it reject\n * with a `SyntaxError` that no `catch` here handles, so it escapes untyped past a caller prepared only\n * for `AuthCallbackError`.\n *\n * The body is quoted, truncated, because \"not JSON\" and \"not JSON, and it looks like a proxy login\n * page\" are different diagnoses for whoever is holding the terminal — and routing them to the provider\n * when the fault is their network is the expensive kind of wrong.\n */\nasync function parseJsonOrFail(res: Response, code: string, what: string): Promise<unknown> {\n const text = await res.text().catch(() => \"\");\n try {\n return JSON.parse(text);\n } catch {\n throw new AuthCallbackError(code, `${what} returned a non-JSON body: ${text.slice(0, 120)}`);\n }\n}\n\n/** Step 1 — request a device code. POSTs `{client_id, scope}` to the device endpoint. */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: RFC 8628 device-code request — cohesive network response parser ported verbatim (ADR D3).\nexport async function requestDeviceCode(\n config: DeviceOAuthConfig,\n deps: Pick<DeviceDeps, \"fetch\">,\n): Promise<DeviceCodeGrant> {\n let res: Response;\n try {\n res = await deps.fetch(config.deviceCodeEndpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\", accept: \"application/json\" },\n body: new URLSearchParams({\n client_id: config.clientId,\n scope: config.scopes.join(\" \"),\n }).toString(),\n });\n } catch (err) {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n `device request failed: ${(err as Error).message}`,\n );\n }\n if (!res.ok) {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n `device endpoint returned HTTP ${res.status}`,\n );\n }\n const data = (await parseJsonOrFail(\n res,\n \"oauth_device_authorization_failed\",\n \"device endpoint\",\n )) as {\n device_code?: unknown;\n user_code?: unknown;\n verification_uri?: unknown;\n verification_uri_complete?: unknown;\n interval?: unknown;\n expires_in?: unknown;\n };\n if (typeof data.device_code !== \"string\" || typeof data.user_code !== \"string\") {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n \"device response missing device_code/user_code\",\n );\n }\n const verification =\n typeof data.verification_uri === \"string\"\n ? data.verification_uri\n : typeof data.verification_uri_complete === \"string\"\n ? data.verification_uri_complete\n : \"\";\n return {\n deviceCode: data.device_code,\n userCode: data.user_code,\n verificationUri: verification,\n interval: typeof data.interval === \"number\" && data.interval > 0 ? data.interval : 5,\n expiresIn: typeof data.expires_in === \"number\" && data.expires_in > 0 ? data.expires_in : 900,\n };\n}\n\n/**\n * Step 2 — poll the token endpoint until the user approves (or the code expires). Handles RFC 8628\n * `authorization_pending` (keep waiting) and `slow_down` (back off), with an expiry deadline so it cannot\n * spin forever.\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: RFC 8628 poll state machine (authorization_pending / slow_down / success / expiry) — a cohesive loop ported verbatim (ADR D3); fragmenting it would obscure the protocol.\nexport async function pollDeviceToken(\n config: DeviceOAuthConfig,\n grant: DeviceCodeGrant,\n deps: DeviceDeps,\n): Promise<OAuthTokens> {\n const deadline = deps.now() + grant.expiresIn * 1000;\n let intervalMs = grant.interval * 1000;\n\n while (deps.now() < deadline) {\n let res: Response;\n try {\n res = await deps.fetch(config.tokenEndpoint, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/x-www-form-urlencoded\",\n accept: \"application/json\",\n },\n body: new URLSearchParams({\n client_id: config.clientId,\n device_code: grant.deviceCode,\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n }).toString(),\n });\n } catch (err) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `device token poll failed: ${(err as Error).message}`,\n );\n }\n // RFC 8628 §3.5: `authorization_pending` / `slow_down` arrive as a 400 with an `error` body — so the\n // body MUST be read before deciding failure. Parse first; only a non-OAuth-shaped body on a non-2xx fails.\n const data = (await res.json().catch(() => ({}))) as {\n access_token?: string;\n refresh_token?: string;\n expires_in?: number;\n id_token?: string;\n error?: string;\n interval?: number;\n };\n if (!res.ok && typeof data.error !== \"string\") {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `device token endpoint returned HTTP ${res.status}`,\n );\n }\n\n if (typeof data.access_token === \"string\" && data.access_token.length > 0) {\n const expiresIn = typeof data.expires_in === \"number\" ? data.expires_in : 0;\n const accountId = extractAccountId({\n access_token: data.access_token,\n id_token: data.id_token,\n });\n return {\n access: data.access_token,\n // Some device-grant providers (e.g. GitHub) issue no separate refresh token — reuse the access\n // token as the refresh handle.\n refresh: data.refresh_token ?? data.access_token,\n expires: deps.now() + expiresIn * 1000,\n ...(accountId !== undefined ? { accountId } : {}),\n };\n }\n\n if (data.error === \"authorization_pending\") {\n await deps.sleep(intervalMs + POLLING_SAFETY_MARGIN_MS);\n continue;\n }\n if (data.error === \"slow_down\") {\n // RFC 8628 §3.5: add 5s to the interval, or honor a server-provided one.\n intervalMs =\n (typeof data.interval === \"number\" && data.interval > 0\n ? data.interval\n : grant.interval + 5) * 1000;\n await deps.sleep(intervalMs + POLLING_SAFETY_MARGIN_MS);\n continue;\n }\n if (typeof data.error === \"string\") {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `device authorization rejected: ${data.error}`,\n );\n }\n await deps.sleep(intervalMs + POLLING_SAFETY_MARGIN_MS);\n }\n throw new AuthCallbackError(\n \"oauth_device_code_expired\",\n \"the device code expired before it was approved\",\n );\n}\n\n/**\n * The full device login: request a code, hand the user the verification URL + user code via `onPrompt`\n * (never printed here — the caller renders it, keeping this module output-free), then poll to completion.\n */\nexport async function deviceLogin(\n config: DeviceOAuthConfig,\n deps: DeviceDeps,\n hooks: {\n onPrompt: (p: { userCode: string; verificationUri: string; expiresIn: number }) => void;\n },\n): Promise<OAuthTokens> {\n const grant = await requestDeviceCode(config, deps);\n hooks.onPrompt({\n userCode: grant.userCode,\n verificationUri: grant.verificationUri,\n expiresIn: grant.expiresIn,\n });\n return pollDeviceToken(config, grant, deps);\n}\n\n// ─── OpenAI / ChatGPT \"headless\" device flow (two-step) ───\n\n/** Step 1 (OpenAI) — request the user code. */\nexport async function requestOpenAIUsercode(\n config: OpenAIDeviceConfig,\n deps: Pick<DeviceDeps, \"fetch\">,\n): Promise<{ deviceAuthId: string; userCode: string; interval: number }> {\n let res: Response;\n try {\n res = await deps.fetch(config.deviceUsercodeEndpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", accept: \"application/json\" },\n body: JSON.stringify({ client_id: config.clientId }),\n });\n } catch (err) {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n `usercode request failed: ${(err as Error).message}`,\n );\n }\n if (!res.ok) {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n `usercode endpoint returned HTTP ${res.status}`,\n );\n }\n const data = (await parseJsonOrFail(\n res,\n \"oauth_device_authorization_failed\",\n \"usercode endpoint\",\n )) as {\n device_auth_id?: unknown;\n user_code?: unknown;\n interval?: unknown;\n };\n if (typeof data.device_auth_id !== \"string\" || typeof data.user_code !== \"string\") {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n \"usercode response missing device_auth_id/user_code\",\n );\n }\n const interval = Math.max(\n typeof data.interval === \"string\" ? parseInt(data.interval, 10) || 5 : 5,\n 1,\n );\n return { deviceAuthId: data.device_auth_id, userCode: data.user_code, interval };\n}\n\n/**\n * Step 2+3 (OpenAI) — poll for the authorization code (200 = ready; 403/404 = pending; else fail), then\n * exchange it for tokens at the standard `/oauth/token` endpoint (reuses `exchangeCode`).\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: OpenAI two-step headless poll loop (200 ready / 403,404 pending / else fail) — cohesive network state machine ported verbatim (ADR D3).\nexport async function openaiDeviceLogin(\n config: OpenAIDeviceConfig,\n deps: DeviceDeps,\n hooks: { onPrompt: (p: { userCode: string; verificationUri: string }) => void },\n): Promise<OAuthTokens> {\n const { deviceAuthId, userCode, interval } = await requestOpenAIUsercode(config, deps);\n hooks.onPrompt({ userCode, verificationUri: config.verificationUri });\n\n const intervalMs = interval * 1000;\n // Bound the loop so it cannot spin forever if the provider never resolves (upstream loops unbounded).\n const deadline = deps.now() + 15 * 60 * 1000;\n while (deps.now() < deadline) {\n let res: Response;\n try {\n res = await deps.fetch(config.devicePollEndpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", accept: \"application/json\" },\n body: JSON.stringify({ device_auth_id: deviceAuthId, user_code: userCode }),\n });\n } catch (err) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `device poll failed: ${(err as Error).message}`,\n );\n }\n if (res.ok) {\n const data = (await parseJsonOrFail(res, \"oauth_token_exchange_failed\", \"device poll\")) as {\n authorization_code?: unknown;\n code_verifier?: unknown;\n };\n if (typeof data.authorization_code !== \"string\" || typeof data.code_verifier !== \"string\") {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n \"device poll returned no authorization_code\",\n );\n }\n const tokens = await exchangeCode(\n config,\n { code: data.authorization_code, verifier: data.code_verifier },\n deps,\n );\n // M43 D4 fix #2 — the two-step exchange returns a JWT access token but `parseTokenResponse` only reads a\n // top-level `account_id`. JWT-extract the `chatgpt_account_id` (as the generic device poll already does)\n // so the login persists a non-empty account_id for the Codex `ChatGPT-Account-Id` header.\n return {\n ...tokens,\n accountId: tokens.accountId ?? extractAccountId({ access_token: tokens.access }),\n };\n }\n // 403/404 = still pending (user has not approved yet); anything else is a hard failure.\n if (res.status !== 403 && res.status !== 404) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `device poll returned HTTP ${res.status}`,\n );\n }\n await deps.sleep(intervalMs + POLLING_SAFETY_MARGIN_MS);\n }\n throw new AuthCallbackError(\n \"oauth_device_code_expired\",\n \"the device authorization expired before approval\",\n );\n}\n\n/** JWT id/access-token claims we read to attribute an account. */\ninterface IdTokenClaims {\n chatgpt_account_id?: string;\n organizations?: Array<{ id: string }>;\n \"https://api.openai.com/auth\"?: { chatgpt_account_id?: string };\n}\n\n/** Decode a JWT's claim set (no signature verification — used only to read a self-reported account id). */\nexport function parseJwtClaims(token: string): IdTokenClaims | undefined {\n const parts = token.split(\".\");\n if (parts.length !== 3) return undefined;\n try {\n return JSON.parse(Buffer.from(parts[1] as string, \"base64url\").toString()) as IdTokenClaims;\n } catch {\n return undefined;\n }\n}\n\n/** Best-effort account id from an id/access token's claims (OpenAI/ChatGPT shape). */\nexport function extractAccountId(tokens: {\n id_token?: string;\n access_token?: string;\n}): string | undefined {\n for (const token of [tokens.id_token, tokens.access_token]) {\n if (token === undefined) continue;\n const claims = parseJwtClaims(token);\n const id =\n claims?.chatgpt_account_id ??\n claims?.[\"https://api.openai.com/auth\"]?.chatgpt_account_id ??\n claims?.organizations?.[0]?.id;\n if (id !== undefined) return id;\n }\n return undefined;\n}\n"]}
|
package/dist/auth/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export { providerFromApiKeyPrefix } from '../chunk-NAF4L3T6.js';
|
|
2
|
-
import { exchangeCode } from '../chunk-
|
|
3
|
-
export { ensureFreshCredential, exchangeCode, persistOAuthTokens, refreshOAuthTokens, resolveCredential } from '../chunk-
|
|
2
|
+
import { exchangeCode } from '../chunk-TX56N7FR.js';
|
|
3
|
+
export { ensureFreshCredential, exchangeCode, persistOAuthTokens, refreshOAuthTokens, resolveCredential } from '../chunk-TX56N7FR.js';
|
|
4
4
|
export { CredentialError, assertSecureModes, authFilePath, credentialHome, readAuthFile, readStoredOAuth, writeCredential } from '../chunk-5Q4RTLMP.js';
|
|
5
5
|
import { AuthCallbackError } from '../chunk-H3CVJSFC.js';
|
|
6
|
+
import '../chunk-Q7GYMXVC.js';
|
|
6
7
|
import '../chunk-B5MHRQJZ.js';
|
|
7
8
|
import '../chunk-CZJ6Q7CW.js';
|
|
8
9
|
|
package/dist/auth/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/internal/auth/oauth-device.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * M42 — the SDK OAuth device-authorization flows (RFC 8628 + OpenAI two-step headless). Split out of\n * oauth-engine.ts to respect the 500-line file budget; a sibling of the core engine. Promoted DOWN from\n * agent-builder's hardened `agents/lib/oauth-device.ts` (M37).\n *\n * Implements two device flows against their published specs: the RFC 8628 device-grant poll loop\n * (device_code → authorization_pending / slow_down) and OpenAI's two-step headless flow, including the\n * JWT-claim / account-id extraction used to attribute an account.\n * Design choices: network I/O + clock + sleep are INJECTED (deterministic tests), failures raise the SDK's\n * typed `AuthCallbackError`, and a device-code expiry DEADLINE guards each poll loop.\n *\n * @internal\n */\nimport { AuthCallbackError } from \"../../server/auth/errors.js\";\nimport { exchangeCode } from \"./oauth-engine.js\";\nimport type {\n DeviceCodeGrant,\n DeviceDeps,\n DeviceOAuthConfig,\n OAuthTokens,\n OpenAIDeviceConfig,\n} from \"./types.js\";\n\n// ─── OAuth 2.0 Device Authorization Grant (RFC 8628) — terminal-first / headless login ───\n\n/** Buffer added to every poll interval to avoid hitting the server a hair early. */\nconst POLLING_SAFETY_MARGIN_MS = 3000;\n\n/**\n * Parse a JSON body, or fail with this module's typed error instead of a raw `SyntaxError`.\n *\n * Every failure in this file is supposed to reach the caller as an `AuthCallbackError` carrying a code\n * the CLI can branch on. `res.json()` breaks that contract: a device endpoint that answers with HTML —\n * a captive portal, a corporate proxy's sign-in page, a load balancer's error page — makes it reject\n * with a `SyntaxError` that no `catch` here handles, so it escapes untyped past a caller prepared only\n * for `AuthCallbackError`.\n *\n * The body is quoted, truncated, because \"not JSON\" and \"not JSON, and it looks like a proxy login\n * page\" are different diagnoses for whoever is holding the terminal — and routing them to the provider\n * when the fault is their network is the expensive kind of wrong.\n */\nasync function parseJsonOrFail(res: Response, code: string, what: string): Promise<unknown> {\n const text = await res.text().catch(() => \"\");\n try {\n return JSON.parse(text);\n } catch {\n throw new AuthCallbackError(code, `${what} returned a non-JSON body: ${text.slice(0, 120)}`);\n }\n}\n\n/** Step 1 — request a device code. POSTs `{client_id, scope}` to the device endpoint. */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: RFC 8628 device-code request — cohesive network response parser ported verbatim (ADR D3).\nexport async function requestDeviceCode(\n config: DeviceOAuthConfig,\n deps: Pick<DeviceDeps, \"fetch\">,\n): Promise<DeviceCodeGrant> {\n let res: Response;\n try {\n res = await deps.fetch(config.deviceCodeEndpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\", accept: \"application/json\" },\n body: new URLSearchParams({\n client_id: config.clientId,\n scope: config.scopes.join(\" \"),\n }).toString(),\n });\n } catch (err) {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n `device request failed: ${(err as Error).message}`,\n );\n }\n if (!res.ok) {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n `device endpoint returned HTTP ${res.status}`,\n );\n }\n const data = (await parseJsonOrFail(\n res,\n \"oauth_device_authorization_failed\",\n \"device endpoint\",\n )) as {\n device_code?: unknown;\n user_code?: unknown;\n verification_uri?: unknown;\n verification_uri_complete?: unknown;\n interval?: unknown;\n expires_in?: unknown;\n };\n if (typeof data.device_code !== \"string\" || typeof data.user_code !== \"string\") {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n \"device response missing device_code/user_code\",\n );\n }\n const verification =\n typeof data.verification_uri === \"string\"\n ? data.verification_uri\n : typeof data.verification_uri_complete === \"string\"\n ? data.verification_uri_complete\n : \"\";\n return {\n deviceCode: data.device_code,\n userCode: data.user_code,\n verificationUri: verification,\n interval: typeof data.interval === \"number\" && data.interval > 0 ? data.interval : 5,\n expiresIn: typeof data.expires_in === \"number\" && data.expires_in > 0 ? data.expires_in : 900,\n };\n}\n\n/**\n * Step 2 — poll the token endpoint until the user approves (or the code expires). Handles RFC 8628\n * `authorization_pending` (keep waiting) and `slow_down` (back off), with an expiry deadline so it cannot\n * spin forever.\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: RFC 8628 poll state machine (authorization_pending / slow_down / success / expiry) — a cohesive loop ported verbatim (ADR D3); fragmenting it would obscure the protocol.\nexport async function pollDeviceToken(\n config: DeviceOAuthConfig,\n grant: DeviceCodeGrant,\n deps: DeviceDeps,\n): Promise<OAuthTokens> {\n const deadline = deps.now() + grant.expiresIn * 1000;\n let intervalMs = grant.interval * 1000;\n\n while (deps.now() < deadline) {\n let res: Response;\n try {\n res = await deps.fetch(config.tokenEndpoint, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/x-www-form-urlencoded\",\n accept: \"application/json\",\n },\n body: new URLSearchParams({\n client_id: config.clientId,\n device_code: grant.deviceCode,\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n }).toString(),\n });\n } catch (err) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `device token poll failed: ${(err as Error).message}`,\n );\n }\n // RFC 8628 §3.5: `authorization_pending` / `slow_down` arrive as a 400 with an `error` body — so the\n // body MUST be read before deciding failure. Parse first; only a non-OAuth-shaped body on a non-2xx fails.\n const data = (await res.json().catch(() => ({}))) as {\n access_token?: string;\n refresh_token?: string;\n expires_in?: number;\n id_token?: string;\n error?: string;\n interval?: number;\n };\n if (!res.ok && typeof data.error !== \"string\") {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `device token endpoint returned HTTP ${res.status}`,\n );\n }\n\n if (typeof data.access_token === \"string\" && data.access_token.length > 0) {\n const expiresIn = typeof data.expires_in === \"number\" ? data.expires_in : 0;\n const accountId = extractAccountId({\n access_token: data.access_token,\n id_token: data.id_token,\n });\n return {\n access: data.access_token,\n // Some device-grant providers (e.g. GitHub) issue no separate refresh token — reuse the access\n // token as the refresh handle.\n refresh: data.refresh_token ?? data.access_token,\n expires: deps.now() + expiresIn * 1000,\n ...(accountId !== undefined ? { accountId } : {}),\n };\n }\n\n if (data.error === \"authorization_pending\") {\n await deps.sleep(intervalMs + POLLING_SAFETY_MARGIN_MS);\n continue;\n }\n if (data.error === \"slow_down\") {\n // RFC 8628 §3.5: add 5s to the interval, or honor a server-provided one.\n intervalMs =\n (typeof data.interval === \"number\" && data.interval > 0\n ? data.interval\n : grant.interval + 5) * 1000;\n await deps.sleep(intervalMs + POLLING_SAFETY_MARGIN_MS);\n continue;\n }\n if (typeof data.error === \"string\") {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `device authorization rejected: ${data.error}`,\n );\n }\n await deps.sleep(intervalMs + POLLING_SAFETY_MARGIN_MS);\n }\n throw new AuthCallbackError(\n \"oauth_device_code_expired\",\n \"the device code expired before it was approved\",\n );\n}\n\n/**\n * The full device login: request a code, hand the user the verification URL + user code via `onPrompt`\n * (never printed here — the caller renders it, keeping this module output-free), then poll to completion.\n */\nexport async function deviceLogin(\n config: DeviceOAuthConfig,\n deps: DeviceDeps,\n hooks: {\n onPrompt: (p: { userCode: string; verificationUri: string; expiresIn: number }) => void;\n },\n): Promise<OAuthTokens> {\n const grant = await requestDeviceCode(config, deps);\n hooks.onPrompt({\n userCode: grant.userCode,\n verificationUri: grant.verificationUri,\n expiresIn: grant.expiresIn,\n });\n return pollDeviceToken(config, grant, deps);\n}\n\n// ─── OpenAI / ChatGPT \"headless\" device flow (two-step) ───\n\n/** Step 1 (OpenAI) — request the user code. */\nexport async function requestOpenAIUsercode(\n config: OpenAIDeviceConfig,\n deps: Pick<DeviceDeps, \"fetch\">,\n): Promise<{ deviceAuthId: string; userCode: string; interval: number }> {\n let res: Response;\n try {\n res = await deps.fetch(config.deviceUsercodeEndpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", accept: \"application/json\" },\n body: JSON.stringify({ client_id: config.clientId }),\n });\n } catch (err) {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n `usercode request failed: ${(err as Error).message}`,\n );\n }\n if (!res.ok) {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n `usercode endpoint returned HTTP ${res.status}`,\n );\n }\n const data = (await parseJsonOrFail(\n res,\n \"oauth_device_authorization_failed\",\n \"usercode endpoint\",\n )) as {\n device_auth_id?: unknown;\n user_code?: unknown;\n interval?: unknown;\n };\n if (typeof data.device_auth_id !== \"string\" || typeof data.user_code !== \"string\") {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n \"usercode response missing device_auth_id/user_code\",\n );\n }\n const interval = Math.max(\n typeof data.interval === \"string\" ? parseInt(data.interval, 10) || 5 : 5,\n 1,\n );\n return { deviceAuthId: data.device_auth_id, userCode: data.user_code, interval };\n}\n\n/**\n * Step 2+3 (OpenAI) — poll for the authorization code (200 = ready; 403/404 = pending; else fail), then\n * exchange it for tokens at the standard `/oauth/token` endpoint (reuses `exchangeCode`).\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: OpenAI two-step headless poll loop (200 ready / 403,404 pending / else fail) — cohesive network state machine ported verbatim (ADR D3).\nexport async function openaiDeviceLogin(\n config: OpenAIDeviceConfig,\n deps: DeviceDeps,\n hooks: { onPrompt: (p: { userCode: string; verificationUri: string }) => void },\n): Promise<OAuthTokens> {\n const { deviceAuthId, userCode, interval } = await requestOpenAIUsercode(config, deps);\n hooks.onPrompt({ userCode, verificationUri: config.verificationUri });\n\n const intervalMs = interval * 1000;\n // Bound the loop so it cannot spin forever if the provider never resolves (upstream loops unbounded).\n const deadline = deps.now() + 15 * 60 * 1000;\n while (deps.now() < deadline) {\n let res: Response;\n try {\n res = await deps.fetch(config.devicePollEndpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", accept: \"application/json\" },\n body: JSON.stringify({ device_auth_id: deviceAuthId, user_code: userCode }),\n });\n } catch (err) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `device poll failed: ${(err as Error).message}`,\n );\n }\n if (res.ok) {\n const data = (await parseJsonOrFail(res, \"oauth_token_exchange_failed\", \"device poll\")) as {\n authorization_code?: unknown;\n code_verifier?: unknown;\n };\n if (typeof data.authorization_code !== \"string\" || typeof data.code_verifier !== \"string\") {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n \"device poll returned no authorization_code\",\n );\n }\n const tokens = await exchangeCode(\n config,\n { code: data.authorization_code, verifier: data.code_verifier },\n deps,\n );\n // M43 D4 fix #2 — the two-step exchange returns a JWT access token but `parseTokenResponse` only reads a\n // top-level `account_id`. JWT-extract the `chatgpt_account_id` (as the generic device poll already does)\n // so the login persists a non-empty account_id for the Codex `ChatGPT-Account-Id` header.\n return {\n ...tokens,\n accountId: tokens.accountId ?? extractAccountId({ access_token: tokens.access }),\n };\n }\n // 403/404 = still pending (user has not approved yet); anything else is a hard failure.\n if (res.status !== 403 && res.status !== 404) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `device poll returned HTTP ${res.status}`,\n );\n }\n await deps.sleep(intervalMs + POLLING_SAFETY_MARGIN_MS);\n }\n throw new AuthCallbackError(\n \"oauth_device_code_expired\",\n \"the device authorization expired before approval\",\n );\n}\n\n/** JWT id/access-token claims we read to attribute an account. */\ninterface IdTokenClaims {\n chatgpt_account_id?: string;\n organizations?: Array<{ id: string }>;\n \"https://api.openai.com/auth\"?: { chatgpt_account_id?: string };\n}\n\n/** Decode a JWT's claim set (no signature verification — used only to read a self-reported account id). */\nexport function parseJwtClaims(token: string): IdTokenClaims | undefined {\n const parts = token.split(\".\");\n if (parts.length !== 3) return undefined;\n try {\n return JSON.parse(Buffer.from(parts[1] as string, \"base64url\").toString()) as IdTokenClaims;\n } catch {\n return undefined;\n }\n}\n\n/** Best-effort account id from an id/access token's claims (OpenAI/ChatGPT shape). */\nexport function extractAccountId(tokens: {\n id_token?: string;\n access_token?: string;\n}): string | undefined {\n for (const token of [tokens.id_token, tokens.access_token]) {\n if (token === undefined) continue;\n const claims = parseJwtClaims(token);\n const id =\n claims?.chatgpt_account_id ??\n claims?.[\"https://api.openai.com/auth\"]?.chatgpt_account_id ??\n claims?.organizations?.[0]?.id;\n if (id !== undefined) return id;\n }\n return undefined;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/internal/auth/oauth-device.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * M42 — the SDK OAuth device-authorization flows (RFC 8628 + OpenAI two-step headless). Split out of\n * oauth-engine.ts to respect the 500-line file budget; a sibling of the core engine. Promoted DOWN from\n * agent-builder's hardened `agents/lib/oauth-device.ts` (M37).\n *\n * Implements two device flows against their published specs: the RFC 8628 device-grant poll loop\n * (device_code → authorization_pending / slow_down) and OpenAI's two-step headless flow, including the\n * JWT-claim / account-id extraction used to attribute an account.\n * Design choices: network I/O + clock + sleep are INJECTED (deterministic tests), failures raise the SDK's\n * typed `AuthCallbackError`, and a device-code expiry DEADLINE guards each poll loop.\n *\n * @internal\n */\nimport { AuthCallbackError } from \"../../server/auth/errors.js\";\nimport { exchangeCode } from \"./oauth-engine.js\";\nimport type {\n DeviceCodeGrant,\n DeviceDeps,\n DeviceOAuthConfig,\n OAuthTokens,\n OpenAIDeviceConfig,\n} from \"./types.js\";\n\n// ─── OAuth 2.0 Device Authorization Grant (RFC 8628) — terminal-first / headless login ───\n\n/** Buffer added to every poll interval to avoid hitting the server a hair early. */\nconst POLLING_SAFETY_MARGIN_MS = 3000;\n\n/**\n * Parse a JSON body, or fail with this module's typed error instead of a raw `SyntaxError`.\n *\n * Every failure in this file is supposed to reach the caller as an `AuthCallbackError` carrying a code\n * the CLI can branch on. `res.json()` breaks that contract: a device endpoint that answers with HTML —\n * a captive portal, a corporate proxy's sign-in page, a load balancer's error page — makes it reject\n * with a `SyntaxError` that no `catch` here handles, so it escapes untyped past a caller prepared only\n * for `AuthCallbackError`.\n *\n * The body is quoted, truncated, because \"not JSON\" and \"not JSON, and it looks like a proxy login\n * page\" are different diagnoses for whoever is holding the terminal — and routing them to the provider\n * when the fault is their network is the expensive kind of wrong.\n */\nasync function parseJsonOrFail(res: Response, code: string, what: string): Promise<unknown> {\n const text = await res.text().catch(() => \"\");\n try {\n return JSON.parse(text);\n } catch {\n throw new AuthCallbackError(code, `${what} returned a non-JSON body: ${text.slice(0, 120)}`);\n }\n}\n\n/** Step 1 — request a device code. POSTs `{client_id, scope}` to the device endpoint. */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: RFC 8628 device-code request — cohesive network response parser ported verbatim (ADR D3).\nexport async function requestDeviceCode(\n config: DeviceOAuthConfig,\n deps: Pick<DeviceDeps, \"fetch\">,\n): Promise<DeviceCodeGrant> {\n let res: Response;\n try {\n res = await deps.fetch(config.deviceCodeEndpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\", accept: \"application/json\" },\n body: new URLSearchParams({\n client_id: config.clientId,\n scope: config.scopes.join(\" \"),\n }).toString(),\n });\n } catch (err) {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n `device request failed: ${(err as Error).message}`,\n );\n }\n if (!res.ok) {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n `device endpoint returned HTTP ${res.status}`,\n );\n }\n const data = (await parseJsonOrFail(\n res,\n \"oauth_device_authorization_failed\",\n \"device endpoint\",\n )) as {\n device_code?: unknown;\n user_code?: unknown;\n verification_uri?: unknown;\n verification_uri_complete?: unknown;\n interval?: unknown;\n expires_in?: unknown;\n };\n if (typeof data.device_code !== \"string\" || typeof data.user_code !== \"string\") {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n \"device response missing device_code/user_code\",\n );\n }\n const verification =\n typeof data.verification_uri === \"string\"\n ? data.verification_uri\n : typeof data.verification_uri_complete === \"string\"\n ? data.verification_uri_complete\n : \"\";\n return {\n deviceCode: data.device_code,\n userCode: data.user_code,\n verificationUri: verification,\n interval: typeof data.interval === \"number\" && data.interval > 0 ? data.interval : 5,\n expiresIn: typeof data.expires_in === \"number\" && data.expires_in > 0 ? data.expires_in : 900,\n };\n}\n\n/**\n * Step 2 — poll the token endpoint until the user approves (or the code expires). Handles RFC 8628\n * `authorization_pending` (keep waiting) and `slow_down` (back off), with an expiry deadline so it cannot\n * spin forever.\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: RFC 8628 poll state machine (authorization_pending / slow_down / success / expiry) — a cohesive loop ported verbatim (ADR D3); fragmenting it would obscure the protocol.\nexport async function pollDeviceToken(\n config: DeviceOAuthConfig,\n grant: DeviceCodeGrant,\n deps: DeviceDeps,\n): Promise<OAuthTokens> {\n const deadline = deps.now() + grant.expiresIn * 1000;\n let intervalMs = grant.interval * 1000;\n\n while (deps.now() < deadline) {\n let res: Response;\n try {\n res = await deps.fetch(config.tokenEndpoint, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/x-www-form-urlencoded\",\n accept: \"application/json\",\n },\n body: new URLSearchParams({\n client_id: config.clientId,\n device_code: grant.deviceCode,\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n }).toString(),\n });\n } catch (err) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `device token poll failed: ${(err as Error).message}`,\n );\n }\n // RFC 8628 §3.5: `authorization_pending` / `slow_down` arrive as a 400 with an `error` body — so the\n // body MUST be read before deciding failure. Parse first; only a non-OAuth-shaped body on a non-2xx fails.\n const data = (await res.json().catch(() => ({}))) as {\n access_token?: string;\n refresh_token?: string;\n expires_in?: number;\n id_token?: string;\n error?: string;\n interval?: number;\n };\n if (!res.ok && typeof data.error !== \"string\") {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `device token endpoint returned HTTP ${res.status}`,\n );\n }\n\n if (typeof data.access_token === \"string\" && data.access_token.length > 0) {\n const expiresIn = typeof data.expires_in === \"number\" ? data.expires_in : 0;\n const accountId = extractAccountId({\n access_token: data.access_token,\n id_token: data.id_token,\n });\n return {\n access: data.access_token,\n // Some device-grant providers (e.g. GitHub) issue no separate refresh token — reuse the access\n // token as the refresh handle.\n refresh: data.refresh_token ?? data.access_token,\n expires: deps.now() + expiresIn * 1000,\n ...(accountId !== undefined ? { accountId } : {}),\n };\n }\n\n if (data.error === \"authorization_pending\") {\n await deps.sleep(intervalMs + POLLING_SAFETY_MARGIN_MS);\n continue;\n }\n if (data.error === \"slow_down\") {\n // RFC 8628 §3.5: add 5s to the interval, or honor a server-provided one.\n intervalMs =\n (typeof data.interval === \"number\" && data.interval > 0\n ? data.interval\n : grant.interval + 5) * 1000;\n await deps.sleep(intervalMs + POLLING_SAFETY_MARGIN_MS);\n continue;\n }\n if (typeof data.error === \"string\") {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `device authorization rejected: ${data.error}`,\n );\n }\n await deps.sleep(intervalMs + POLLING_SAFETY_MARGIN_MS);\n }\n throw new AuthCallbackError(\n \"oauth_device_code_expired\",\n \"the device code expired before it was approved\",\n );\n}\n\n/**\n * The full device login: request a code, hand the user the verification URL + user code via `onPrompt`\n * (never printed here — the caller renders it, keeping this module output-free), then poll to completion.\n */\nexport async function deviceLogin(\n config: DeviceOAuthConfig,\n deps: DeviceDeps,\n hooks: {\n onPrompt: (p: { userCode: string; verificationUri: string; expiresIn: number }) => void;\n },\n): Promise<OAuthTokens> {\n const grant = await requestDeviceCode(config, deps);\n hooks.onPrompt({\n userCode: grant.userCode,\n verificationUri: grant.verificationUri,\n expiresIn: grant.expiresIn,\n });\n return pollDeviceToken(config, grant, deps);\n}\n\n// ─── OpenAI / ChatGPT \"headless\" device flow (two-step) ───\n\n/** Step 1 (OpenAI) — request the user code. */\nexport async function requestOpenAIUsercode(\n config: OpenAIDeviceConfig,\n deps: Pick<DeviceDeps, \"fetch\">,\n): Promise<{ deviceAuthId: string; userCode: string; interval: number }> {\n let res: Response;\n try {\n res = await deps.fetch(config.deviceUsercodeEndpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", accept: \"application/json\" },\n body: JSON.stringify({ client_id: config.clientId }),\n });\n } catch (err) {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n `usercode request failed: ${(err as Error).message}`,\n );\n }\n if (!res.ok) {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n `usercode endpoint returned HTTP ${res.status}`,\n );\n }\n const data = (await parseJsonOrFail(\n res,\n \"oauth_device_authorization_failed\",\n \"usercode endpoint\",\n )) as {\n device_auth_id?: unknown;\n user_code?: unknown;\n interval?: unknown;\n };\n if (typeof data.device_auth_id !== \"string\" || typeof data.user_code !== \"string\") {\n throw new AuthCallbackError(\n \"oauth_device_authorization_failed\",\n \"usercode response missing device_auth_id/user_code\",\n );\n }\n const interval = Math.max(\n typeof data.interval === \"string\" ? parseInt(data.interval, 10) || 5 : 5,\n 1,\n );\n return { deviceAuthId: data.device_auth_id, userCode: data.user_code, interval };\n}\n\n/**\n * Step 2+3 (OpenAI) — poll for the authorization code (200 = ready; 403/404 = pending; else fail), then\n * exchange it for tokens at the standard `/oauth/token` endpoint (reuses `exchangeCode`).\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: OpenAI two-step headless poll loop (200 ready / 403,404 pending / else fail) — cohesive network state machine ported verbatim (ADR D3).\nexport async function openaiDeviceLogin(\n config: OpenAIDeviceConfig,\n deps: DeviceDeps,\n hooks: { onPrompt: (p: { userCode: string; verificationUri: string }) => void },\n): Promise<OAuthTokens> {\n const { deviceAuthId, userCode, interval } = await requestOpenAIUsercode(config, deps);\n hooks.onPrompt({ userCode, verificationUri: config.verificationUri });\n\n const intervalMs = interval * 1000;\n // Bound the loop so it cannot spin forever if the provider never resolves (upstream loops unbounded).\n const deadline = deps.now() + 15 * 60 * 1000;\n while (deps.now() < deadline) {\n let res: Response;\n try {\n res = await deps.fetch(config.devicePollEndpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", accept: \"application/json\" },\n body: JSON.stringify({ device_auth_id: deviceAuthId, user_code: userCode }),\n });\n } catch (err) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `device poll failed: ${(err as Error).message}`,\n );\n }\n if (res.ok) {\n const data = (await parseJsonOrFail(res, \"oauth_token_exchange_failed\", \"device poll\")) as {\n authorization_code?: unknown;\n code_verifier?: unknown;\n };\n if (typeof data.authorization_code !== \"string\" || typeof data.code_verifier !== \"string\") {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n \"device poll returned no authorization_code\",\n );\n }\n const tokens = await exchangeCode(\n config,\n { code: data.authorization_code, verifier: data.code_verifier },\n deps,\n );\n // M43 D4 fix #2 — the two-step exchange returns a JWT access token but `parseTokenResponse` only reads a\n // top-level `account_id`. JWT-extract the `chatgpt_account_id` (as the generic device poll already does)\n // so the login persists a non-empty account_id for the Codex `ChatGPT-Account-Id` header.\n return {\n ...tokens,\n accountId: tokens.accountId ?? extractAccountId({ access_token: tokens.access }),\n };\n }\n // 403/404 = still pending (user has not approved yet); anything else is a hard failure.\n if (res.status !== 403 && res.status !== 404) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `device poll returned HTTP ${res.status}`,\n );\n }\n await deps.sleep(intervalMs + POLLING_SAFETY_MARGIN_MS);\n }\n throw new AuthCallbackError(\n \"oauth_device_code_expired\",\n \"the device authorization expired before approval\",\n );\n}\n\n/** JWT id/access-token claims we read to attribute an account. */\ninterface IdTokenClaims {\n chatgpt_account_id?: string;\n organizations?: Array<{ id: string }>;\n \"https://api.openai.com/auth\"?: { chatgpt_account_id?: string };\n}\n\n/** Decode a JWT's claim set (no signature verification — used only to read a self-reported account id). */\nexport function parseJwtClaims(token: string): IdTokenClaims | undefined {\n const parts = token.split(\".\");\n if (parts.length !== 3) return undefined;\n try {\n return JSON.parse(Buffer.from(parts[1] as string, \"base64url\").toString()) as IdTokenClaims;\n } catch {\n return undefined;\n }\n}\n\n/** Best-effort account id from an id/access token's claims (OpenAI/ChatGPT shape). */\nexport function extractAccountId(tokens: {\n id_token?: string;\n access_token?: string;\n}): string | undefined {\n for (const token of [tokens.id_token, tokens.access_token]) {\n if (token === undefined) continue;\n const claims = parseJwtClaims(token);\n const id =\n claims?.chatgpt_account_id ??\n claims?.[\"https://api.openai.com/auth\"]?.chatgpt_account_id ??\n claims?.organizations?.[0]?.id;\n if (id !== undefined) return id;\n }\n return undefined;\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { splitFrontmatter, parseSimpleYaml } from './chunk-KVNWIAO4.js';
|
|
2
2
|
import { findGitRoot } from './chunk-4QCJAJAG.js';
|
|
3
3
|
import { sanitizeIdentifier, safePathJoin, safeFilenameForId } from './chunk-5DD4NJN3.js';
|
|
4
|
-
import { encodeProjectDir } from './chunk-
|
|
4
|
+
import { encodeProjectDir } from './chunk-FTZTZBCU.js';
|
|
5
5
|
import { openSqliteResilient } from './chunk-XZHJYSPB.js';
|
|
6
6
|
import { withCwdMutex } from './chunk-Q5EWJPRY.js';
|
|
7
7
|
import { replaceFileAtomic } from './chunk-3JHIFQ4I.js';
|
|
@@ -805,5 +805,5 @@ function lanceStoragePath(root) {
|
|
|
805
805
|
}
|
|
806
806
|
|
|
807
807
|
export { LanceIndex, MEMORY_INDEX_MAX_BYTES, MEMORY_INDEX_MAX_LINES, MEMORY_KINDS, appendFact, appendFactToMarkdown, asMemoryRoot, blendScores, claudeProjectMemoryDir, collectMarkdownFiles, defaultIndexPath, discoverSessionFiles, discoverWikiFiles, indexBudgetWarning, lanceStoragePath, legacyMemoryJsonPath, memoryIndexRoot, memoryMdPath, memoryReadRoots, notesDir, openMemoryDb, projectMemoryDir, readFacts, readFactsFromMarkdown, resolveMemoryRoot, resolveWeights, sessionSummaryPath, sessionsDir, sha256, truncateSnippet, wikiDir, writeSessionSummary };
|
|
808
|
-
//# sourceMappingURL=chunk-
|
|
809
|
-
//# sourceMappingURL=chunk-
|
|
808
|
+
//# sourceMappingURL=chunk-47Z6LP3I.js.map
|
|
809
|
+
//# sourceMappingURL=chunk-47Z6LP3I.js.map
|