@mandujs/core 0.54.31 → 0.55.0-beta.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.
- package/README.md +654 -654
- package/package.json +106 -210
- package/scripts/postinstall-lock.ts +153 -153
- package/src/a11y/__tests__/run-audit.test.ts +333 -333
- package/src/a11y/fix-hints.ts +76 -76
- package/src/a11y/index.ts +18 -18
- package/src/a11y/run-audit.ts +15 -15
- package/src/a11y/types.ts +125 -125
- package/src/agent/__tests__/apply.test.ts +224 -0
- package/src/agent/__tests__/context.test.ts +97 -98
- package/src/agent/apply.ts +1031 -0
- package/src/agent/context.ts +552 -552
- package/src/agent/index.ts +4 -3
- package/src/agent/plan.ts +161 -243
- package/src/agent/repair.ts +239 -162
- package/src/agent/sync.ts +197 -198
- package/src/agent/types.ts +242 -94
- package/src/agent/verify.ts +55 -55
- package/src/auth/__tests__/login.test.ts +1 -1
- package/src/auth/__tests__/password.test.ts +15 -5
- package/src/auth/__tests__/reset.test.ts +2 -2
- package/src/auth/__tests__/tokens.test.ts +274 -274
- package/src/auth/__tests__/verification.test.ts +274 -274
- package/src/auth/index.ts +76 -76
- package/src/auth/login.ts +225 -225
- package/src/auth/password.ts +14 -2
- package/src/auth/reset.ts +243 -243
- package/src/auth/tokens.ts +612 -612
- package/src/auth/verification.ts +253 -253
- package/src/brain/__tests__/redactor.test.ts +94 -94
- package/src/brain/adapters/__tests__/_helpers.ts +83 -83
- package/src/brain/adapters/__tests__/anthropic-oauth.test.ts +196 -196
- package/src/brain/adapters/__tests__/chatgpt-auth.test.ts +193 -193
- package/src/brain/adapters/__tests__/openai-oauth.test.ts +209 -209
- package/src/brain/adapters/__tests__/resolver.test.ts +143 -143
- package/src/brain/adapters/anthropic-oauth.ts +1 -1
- package/src/brain/adapters/chatgpt-auth.ts +300 -300
- package/src/brain/adapters/index.ts +319 -319
- package/src/brain/adapters/oauth-flow.ts +439 -439
- package/src/brain/consent.ts +240 -240
- package/src/brain/credentials.ts +396 -396
- package/src/brain/doctor/analyzer.ts +7 -7
- package/src/bundler/__snapshots__/build.test.ts.snap +5 -5
- package/src/bundler/__tests__/build-runner.ts +166 -166
- package/src/bundler/__tests__/client-boundary-transform.test.ts +524 -524
- package/src/bundler/__tests__/cold-start.test.ts +60 -60
- package/src/bundler/__tests__/css.test.ts +49 -20
- package/src/bundler/__tests__/dev-reliability.test.ts +619 -619
- package/src/bundler/__tests__/extended-watch.test.ts +711 -711
- package/src/bundler/__tests__/fast-refresh.test.ts +24 -24
- package/src/bundler/__tests__/generation.test.ts +447 -0
- package/src/bundler/__tests__/hdr.test.ts +24 -18
- package/src/bundler/__tests__/hmr-client.test.ts +62 -24
- package/src/bundler/__tests__/jsx-runtime-shim.test.ts +179 -140
- package/src/bundler/__tests__/manifest-schema.test.ts +305 -266
- package/src/bundler/__tests__/prod-smoke.test.ts +138 -138
- package/src/bundler/__tests__/reverse-import-graph.test.ts +42 -42
- package/src/bundler/__tests__/slot-dispatch.test.ts +573 -573
- package/src/bundler/__tests__/url-cap-and-slot-regex.test.ts +286 -286
- package/src/bundler/__tests__/vendor-cache.test.ts +455 -455
- package/src/bundler/analyzer.ts +15 -15
- package/src/bundler/budget.ts +404 -404
- package/src/bundler/build.test.ts +898 -915
- package/src/bundler/build.ts +113 -24
- package/src/bundler/client-boundary-transform.ts +977 -977
- package/src/bundler/css.ts +65 -44
- package/src/bundler/dev.ts +105 -73
- package/src/bundler/fast-refresh-preamble.ts +47 -47
- package/src/bundler/generation.ts +602 -0
- package/src/bundler/index.ts +3 -3
- package/src/bundler/manifest-schema.ts +55 -40
- package/src/bundler/plugins/__tests__/block-generated-imports.test.ts +13 -13
- package/src/bundler/plugins/__tests__/react-compiler-config.test.ts +83 -83
- package/src/bundler/plugins/__tests__/react-compiler-lint.test.ts +110 -110
- package/src/bundler/plugins/block-generated-imports.ts +16 -15
- package/src/bundler/plugins/index.ts +83 -83
- package/src/bundler/plugins/react-compiler-config.ts +108 -108
- package/src/bundler/plugins/react-compiler-lint.ts +253 -253
- package/src/bundler/plugins/react-compiler.ts +162 -162
- package/src/bundler/prerender.ts +29 -9
- package/src/bundler/reverse-import-graph.ts +339 -339
- package/src/bundler/safe-build.test.ts +1 -1
- package/src/bundler/safe-build.ts +103 -103
- package/src/bundler/scenario-matrix.ts +229 -229
- package/src/bundler/types.ts +58 -56
- package/src/bundler/vendor-cache-types.ts +130 -130
- package/src/bundler/vendor-cache.ts +526 -526
- package/src/change/snapshot.ts +18 -18
- package/src/client/Form.tsx +105 -105
- package/src/client/Link.tsx +9 -9
- package/src/client/__tests__/props-serialization.test.ts +37 -37
- package/src/client/__tests__/use-sse.test.ts +153 -153
- package/src/client/globals.ts +1 -1
- package/src/client/hooks.ts +362 -362
- package/src/client/hydrate.ts +2 -2
- package/src/client/index.ts +1 -1
- package/src/client/island.ts +79 -79
- package/src/client/prefetch-helper.ts +55 -55
- package/src/client/props-serialization.ts +233 -233
- package/src/client/runtime-entry.ts +598 -598
- package/src/client/runtime.ts +1 -1
- package/src/client/serialize.ts +50 -50
- package/src/client/use-fetch.ts +6 -6
- package/src/client/use-head.ts +197 -197
- package/src/client/use-sse.ts +378 -378
- package/src/client/window-state.ts +101 -101
- package/src/components/Image-compat.ts +3 -0
- package/src/components/Image.tsx +162 -162
- package/src/config/validate.ts +1 -1
- package/src/config/watcher.ts +311 -311
- package/src/constants.ts +40 -40
- package/src/content/collection.ts +9 -9
- package/src/content/content-layer.ts +7 -7
- package/src/content/data-store.ts +245 -245
- package/src/content/frontmatter.ts +189 -189
- package/src/content/generate-types.ts +1 -1
- package/src/content/index.ts +2 -2
- package/src/content/loader-context.ts +171 -171
- package/src/content/loaders/api.ts +216 -216
- package/src/content/loaders/file.ts +172 -172
- package/src/content/loaders/glob.ts +253 -253
- package/src/content/loaders/index.ts +34 -34
- package/src/content/loaders/types.ts +137 -137
- package/src/content/meta-store.ts +209 -209
- package/src/content/prebuild.test.ts +571 -571
- package/src/content/prebuild.ts +636 -636
- package/src/content/schema.ts +20 -20
- package/src/content/sidebar.ts +630 -630
- package/src/content/slug.ts +110 -110
- package/src/content/types.ts +282 -282
- package/src/content/watcher.ts +135 -135
- package/src/contract/client-safe.test.ts +42 -42
- package/src/contract/client-safe.ts +114 -114
- package/src/contract/define.ts +11 -11
- package/src/contract/index.ts +1 -1
- package/src/contract/normalize.test.ts +276 -276
- package/src/contract/normalize.ts +410 -410
- package/src/contract/registry.test.ts +206 -206
- package/src/contract/route-helpers.ts +1 -1
- package/src/contract/rpc.ts +443 -443
- package/src/contract/types.ts +58 -58
- package/src/db/__tests__/db.test.ts +9 -9
- package/src/db/index.ts +2 -2
- package/src/db/migrations/history-table.ts +345 -345
- package/src/db/migrations/index.ts +3 -3
- package/src/db/migrations/lock.ts +324 -324
- package/src/db/migrations/runner.ts +650 -650
- package/src/deploy/cache.ts +140 -140
- package/src/deploy/compile/vercel.ts +344 -344
- package/src/deploy/index.ts +87 -87
- package/src/deploy/inference/brain.ts +268 -268
- package/src/deploy/inference/context.ts +82 -82
- package/src/deploy/inference/filling-extract.ts +245 -245
- package/src/deploy/inference/heuristic.ts +182 -182
- package/src/deploy/intent.ts +173 -173
- package/src/deploy/plan.ts +178 -178
- package/src/design/__tests__/agents-link.test.ts +109 -109
- package/src/design/__tests__/extract-patch-diff.test.ts +265 -265
- package/src/design/__tests__/lint.test.ts +110 -110
- package/src/design/__tests__/parser.test.ts +195 -195
- package/src/design/__tests__/tailwind-theme.test.ts +229 -229
- package/src/design/agents-link.ts +165 -165
- package/src/design/diff.ts +138 -138
- package/src/design/extract.ts +285 -285
- package/src/design/index.ts +102 -102
- package/src/design/lint.ts +209 -209
- package/src/design/parser.ts +555 -555
- package/src/design/patch.ts +241 -241
- package/src/design/scaffold.ts +147 -147
- package/src/design/tailwind-theme.ts +441 -441
- package/src/design/types.ts +210 -210
- package/src/desktop/__tests__/smoke.test.ts +2 -2
- package/src/desktop/__tests__/webview-fallback.test.ts +12 -32
- package/src/desktop/__tests__/window.test.ts +20 -99
- package/src/desktop/__tests__/worker.test.ts +266 -266
- package/src/desktop/index.ts +43 -43
- package/src/desktop/types.ts +158 -158
- package/src/desktop/webview-fallback.ts +17 -4
- package/src/desktop/window.ts +17 -8
- package/src/desktop/worker.ts +180 -180
- package/src/dev-error-overlay/__tests__/overlay-injector.test.ts +241 -241
- package/src/dev-error-overlay/index.ts +30 -30
- package/src/dev-error-overlay/overlay-injector.ts +243 -243
- package/src/dev-error-overlay/overlay-styles.ts +52 -52
- package/src/dev-error-overlay/types.ts +66 -66
- package/src/devtools/ai/context-builder.ts +375 -375
- package/src/devtools/ai/index.ts +25 -25
- package/src/devtools/ai/mcp-connector.ts +25 -25
- package/src/devtools/client/catchers/error-catcher.ts +344 -344
- package/src/devtools/client/catchers/index.ts +18 -18
- package/src/devtools/client/components/index.ts +39 -39
- package/src/devtools/client/components/mandu-character.tsx +331 -331
- package/src/devtools/client/components/panel/errors-panel.tsx +259 -259
- package/src/devtools/client/components/panel/guard-panel.tsx +30 -30
- package/src/devtools/client/components/panel/islands-panel.tsx +16 -16
- package/src/devtools/client/components/panel/network-panel.tsx +291 -291
- package/src/devtools/client/components/panel/panel-container.tsx +1 -1
- package/src/devtools/client/components/panel/preview-panel.tsx +46 -46
- package/src/devtools/client/filters/context-filters.ts +282 -282
- package/src/devtools/client/filters/index.ts +16 -16
- package/src/devtools/client/index.ts +63 -63
- package/src/devtools/hook/create-hook.ts +207 -207
- package/src/devtools/hook/index.ts +13 -13
- package/src/devtools/index.ts +439 -439
- package/src/devtools/init.ts +265 -265
- package/src/devtools/protocol.ts +237 -237
- package/src/devtools/server/index.ts +17 -17
- package/src/devtools/types.ts +35 -35
- package/src/devtools/worker/index.ts +25 -25
- package/src/devtools/worker/redaction-worker.ts +233 -233
- package/src/diagnose/__tests__/checks.test.ts +136 -136
- package/src/diagnose/checks.ts +185 -185
- package/src/diagnose/index.ts +17 -17
- package/src/diagnose/run.ts +10 -10
- package/src/diagnose/types.ts +53 -53
- package/src/email/__tests__/email.test.ts +355 -355
- package/src/email/index.ts +282 -282
- package/src/email/smtp.ts +64 -64
- package/src/error/domains.ts +265 -265
- package/src/error/types.ts +6 -6
- package/src/errors/extractor.ts +409 -409
- package/src/errors/index.ts +19 -19
- package/src/filling/__tests__/session-sqlite.test.ts +5 -1
- package/src/filling/auth.ts +308 -308
- package/src/filling/body-parse.test.ts +60 -60
- package/src/filling/cookie-codec.ts +5 -3
- package/src/filling/deps.ts +265 -265
- package/src/filling/head-method.test.ts +154 -154
- package/src/filling/session-sqlite.ts +617 -617
- package/src/filling/sse.ts +5 -5
- package/src/filling/ws.ts +78 -78
- package/src/generator/generate.ts +30 -30
- package/src/generator/index.ts +3 -3
- package/src/generator/templates.test.ts +48 -48
- package/src/generator/templates.ts +219 -219
- package/src/guard/__tests__/design-inline-class.test.ts +219 -219
- package/src/guard/__tests__/tsgolint-bridge.test.ts +347 -347
- package/src/guard/analyzer.ts +360 -360
- package/src/guard/auto-correct.ts +1 -1
- package/src/guard/check.ts +39 -24
- package/src/guard/config-guard.ts +13 -13
- package/src/guard/contract-guard.ts +9 -9
- package/src/guard/define-rule.ts +243 -243
- package/src/guard/design-inline-class.ts +393 -393
- package/src/guard/file-type.test.ts +24 -24
- package/src/guard/fs-routes-policy.ts +51 -51
- package/src/guard/graph.ts +1 -1
- package/src/guard/healing.ts +36 -36
- package/src/guard/index.ts +11 -11
- package/src/guard/presets/atomic.ts +70 -70
- package/src/guard/presets/clean.ts +77 -77
- package/src/guard/presets/fsd.ts +79 -79
- package/src/guard/presets/hexagonal.ts +68 -68
- package/src/guard/reporter.ts +442 -442
- package/src/guard/rule-presets.ts +379 -379
- package/src/guard/semantic-slots.ts +1 -1
- package/src/guard/suggestions.ts +358 -358
- package/src/guard/tsgolint-bridge.ts +512 -512
- package/src/guard/types.ts +348 -348
- package/src/guard/watcher.ts +405 -405
- package/src/i18n/define.ts +126 -126
- package/src/i18n/index.ts +52 -52
- package/src/i18n/message-registry.ts +173 -173
- package/src/i18n/types.ts +112 -112
- package/src/id/__tests__/id.test.ts +3 -3
- package/src/id/index.ts +105 -105
- package/src/index.ts +9 -48
- package/src/internal/client-boundary.ts +266 -266
- package/src/internal/index.ts +2 -2
- package/src/kitchen/api/agent-devtools-api.ts +779 -779
- package/src/kitchen/api/bundle-inspector.ts +179 -0
- package/src/kitchen/api/errors-grouping.ts +126 -126
- package/src/kitchen/api/file-api.ts +11 -11
- package/src/kitchen/kitchen-handler.ts +36 -0
- package/src/kitchen/kitchen-ui.ts +456 -0
- package/src/logging/index.ts +22 -22
- package/src/logging/transports.ts +365 -365
- package/src/middleware/bridge.ts +147 -147
- package/src/middleware/compose.ts +134 -134
- package/src/middleware/compress.ts +62 -62
- package/src/middleware/cors.ts +47 -47
- package/src/middleware/csrf.ts +328 -328
- package/src/middleware/define.ts +132 -132
- package/src/middleware/jwt.ts +134 -134
- package/src/middleware/logger.ts +58 -58
- package/src/middleware/oauth/__tests__/oauth.test.ts +1 -1
- package/src/middleware/oauth/index.ts +505 -505
- package/src/middleware/oauth/providers.ts +115 -115
- package/src/middleware/rate-limit/index.ts +522 -522
- package/src/middleware/rate-limit/sqlite-store.ts +382 -382
- package/src/middleware/scheduler-cron.ts +96 -96
- package/src/middleware/secure/__tests__/secure.test.ts +360 -360
- package/src/middleware/secure/csp.ts +193 -193
- package/src/middleware/session.ts +174 -174
- package/src/middleware/timeout.ts +55 -55
- package/src/observability/logger-adapter.ts +36 -36
- package/src/observability/sqlite-store.ts +254 -254
- package/src/openapi/generator.ts +1 -1
- package/src/openapi/openapi.test.ts +43 -43
- package/src/perf/__tests__/user-marks.test.ts +354 -354
- package/src/perf/index.ts +133 -133
- package/src/perf/user-marks.ts +1 -1
- package/src/plugins/__tests__/lifecycle-integration.test.ts +272 -272
- package/src/plugins/__tests__/runner.test.ts +409 -409
- package/src/plugins/define.ts +124 -124
- package/src/plugins/examples/dep-check-plugin.ts +80 -80
- package/src/plugins/examples/prerender-cache-plugin.ts +111 -111
- package/src/plugins/examples/sitemap-plugin.ts +65 -65
- package/src/plugins/runner.ts +361 -361
- package/src/plugins/types.ts +368 -368
- package/src/report/index.ts +1 -1
- package/src/resource/__tests__/generator.test.ts +7 -7
- package/src/resource/__tests__/schema.test.ts +14 -14
- package/src/resource/ddl/__tests__/diff.test.ts +639 -639
- package/src/resource/ddl/__tests__/emit.test.ts +165 -165
- package/src/resource/ddl/__tests__/snapshot.test.ts +499 -499
- package/src/resource/ddl/emit.ts +146 -146
- package/src/resource/ddl/persistence-types.ts +218 -218
- package/src/resource/ddl/type-map.ts +223 -223
- package/src/resource/ddl/types.ts +232 -232
- package/src/resource/generator-repo.ts +630 -630
- package/src/resource/generator-schema.ts +11 -11
- package/src/resource/generators/slot.ts +72 -72
- package/src/resource/schema.ts +21 -21
- package/src/router/client-entry.test.ts +227 -227
- package/src/router/client-entry.ts +218 -218
- package/src/router/fs-patterns.test.ts +96 -96
- package/src/router/fs-routes.test.ts +532 -532
- package/src/router/fs-routes.ts +53 -53
- package/src/router/fs-scanner.ts +216 -216
- package/src/router/fs-types.ts +19 -19
- package/src/router/route-source-analyzer.ts +521 -521
- package/src/routes/index.ts +74 -74
- package/src/routes/metadata-routes.ts +427 -427
- package/src/routes/types.ts +341 -341
- package/src/runtime/__tests__/devtools-adapter.test.ts +68 -68
- package/src/runtime/__tests__/error-boundary-redaction.test.ts +141 -141
- package/src/runtime/__tests__/hdr-client.test.ts +223 -223
- package/src/runtime/__tests__/http-errors.test.ts +117 -117
- package/src/runtime/__tests__/inline-client-hydration.test.ts +237 -237
- package/src/runtime/__tests__/not-found.test.ts +152 -152
- package/src/runtime/__tests__/observability-lifecycle.test.ts +103 -103
- package/src/runtime/__tests__/page-render-response.test.ts +517 -517
- package/src/runtime/__tests__/request-middleware.test.ts +70 -70
- package/src/runtime/__tests__/searchparams-page-props.test.ts +81 -81
- package/src/runtime/adapter.ts +47 -47
- package/src/runtime/boundary.tsx +252 -252
- package/src/runtime/cache.ts +494 -494
- package/src/runtime/compose.ts +222 -222
- package/src/runtime/devtools-adapter.ts +68 -68
- package/src/runtime/escape.ts +34 -34
- package/src/runtime/fast-refresh-runtime.ts +322 -322
- package/src/runtime/fast-refresh-types.ts +1 -1
- package/src/runtime/handler.ts +65 -65
- package/src/runtime/handlers.ts +30 -11
- package/src/runtime/http-errors.ts +113 -113
- package/src/runtime/image-handler.ts +1 -1
- package/src/runtime/lifecycle.ts +381 -381
- package/src/runtime/logger.test.ts +345 -345
- package/src/runtime/middleware.ts +264 -264
- package/src/runtime/not-found.ts +93 -93
- package/src/runtime/observability-lifecycle.ts +290 -290
- package/src/runtime/openapi-endpoint.ts +236 -236
- package/src/runtime/page-render-response.ts +287 -274
- package/src/runtime/ppr.ts +74 -74
- package/src/runtime/rate-limit.ts +1 -1
- package/src/runtime/redirect.ts +1 -1
- package/src/runtime/registry.ts +171 -171
- package/src/runtime/request-middleware.ts +31 -31
- package/src/runtime/router.test.ts +4 -4
- package/src/runtime/router.ts +10 -10
- package/src/runtime/server.ts +39 -20
- package/src/runtime/shims.ts +48 -48
- package/src/runtime/ssr.ts +43 -17
- package/src/runtime/static-files.ts +369 -289
- package/src/runtime/streaming-ssr.ts +219 -180
- package/src/runtime/trace.ts +144 -144
- package/src/scheduler/__tests__/scheduler.test.ts +12 -11
- package/src/scheduler/index.ts +11 -5
- package/src/scheduler/validate.ts +169 -169
- package/src/seo/index.ts +219 -219
- package/src/seo/integration/ssr.ts +306 -306
- package/src/seo/render/basic.ts +435 -435
- package/src/seo/render/index.ts +143 -143
- package/src/seo/render/jsonld.ts +539 -539
- package/src/seo/render/opengraph.ts +197 -197
- package/src/seo/render/robots.ts +116 -116
- package/src/seo/render/sitemap.ts +137 -137
- package/src/seo/render/twitter.ts +127 -127
- package/src/seo/resolve/opengraph.ts +143 -143
- package/src/seo/resolve/robots.ts +73 -73
- package/src/seo/resolve/title.ts +94 -94
- package/src/seo/resolve/twitter.ts +73 -73
- package/src/seo/resolve/url.ts +104 -104
- package/src/seo/routes/index.ts +290 -290
- package/src/seo/types.ts +588 -588
- package/src/slot/validator.ts +39 -39
- package/src/spec/schema.ts +35 -35
- package/src/storage/s3/__tests__/s3.test.ts +479 -479
- package/src/storage/s3/index.ts +412 -412
- package/src/testing/__tests__/assertions.test.ts +632 -632
- package/src/testing/__tests__/reporter.test.ts +454 -454
- package/src/testing/assertions.ts +986 -986
- package/src/testing/db.ts +157 -157
- package/src/testing/index.ts +9 -3
- package/src/testing/lcov.ts +192 -0
- package/src/testing/mocks.ts +203 -203
- package/src/testing/session.ts +190 -190
- package/src/types/branded.ts +56 -56
- package/src/types/index.ts +1 -1
- package/src/utils/safe-io.ts +188 -188
- package/src/utils/string-safe.ts +298 -298
- package/src/watcher/__tests__/watcher.test.ts +59 -59
- package/src/watcher/watcher.ts +61 -61
|
@@ -1,196 +1,196 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for `packages/core/src/brain/adapters/anthropic-oauth.ts`.
|
|
3
|
-
*
|
|
4
|
-
* Mirror-image of the OpenAI adapter test file. We reuse the shared
|
|
5
|
-
* in-memory credential store fixture + stub HTTP client, and exercise
|
|
6
|
-
* the Messages-API-specific quirks (system split, 401 refresh,
|
|
7
|
-
* stop_sequences mapping).
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { describe, it, expect, beforeEach } from "bun:test";
|
|
11
|
-
import { promises as fs } from "node:fs";
|
|
12
|
-
import os from "node:os";
|
|
13
|
-
import path from "node:path";
|
|
14
|
-
import {
|
|
15
|
-
AnthropicOAuthAdapter,
|
|
16
|
-
ANTHROPIC_DEFAULT_MODEL,
|
|
17
|
-
} from "../anthropic-oauth";
|
|
18
|
-
import {
|
|
19
|
-
makeMemoryStore,
|
|
20
|
-
makeStubHttpClient,
|
|
21
|
-
FAKE_ENDPOINTS,
|
|
22
|
-
jsonResponse,
|
|
23
|
-
} from "./_helpers";
|
|
24
|
-
import type { StoredToken } from "../../credentials";
|
|
25
|
-
|
|
26
|
-
let tmp: string;
|
|
27
|
-
|
|
28
|
-
beforeEach(async () => {
|
|
29
|
-
tmp = await fs.mkdtemp(path.join(os.tmpdir(), "mandu-anthropic-adapter-"));
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
function seedToken(): StoredToken {
|
|
33
|
-
return {
|
|
34
|
-
access_token: "seed-access",
|
|
35
|
-
refresh_token: "seed-refresh",
|
|
36
|
-
expires_at: Math.floor(Date.now() / 1000) + 3600,
|
|
37
|
-
default_model: ANTHROPIC_DEFAULT_MODEL,
|
|
38
|
-
provider: "anthropic",
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
describe("AnthropicOAuthAdapter — shape + defaults", () => {
|
|
43
|
-
it("reports adapter name anthropic-oauth and default Haiku model", async () => {
|
|
44
|
-
const store = makeMemoryStore({ anthropic: seedToken() });
|
|
45
|
-
const adapter = new AnthropicOAuthAdapter({
|
|
46
|
-
credentialStore: store,
|
|
47
|
-
projectRoot: tmp,
|
|
48
|
-
endpoints: FAKE_ENDPOINTS,
|
|
49
|
-
httpClient: makeStubHttpClient(() => jsonResponse({ content: [] })),
|
|
50
|
-
skipConsent: true,
|
|
51
|
-
});
|
|
52
|
-
expect(adapter.name).toBe("anthropic-oauth");
|
|
53
|
-
expect(adapter.model).toBe(ANTHROPIC_DEFAULT_MODEL);
|
|
54
|
-
const status = await adapter.checkStatus();
|
|
55
|
-
expect(status.available).toBe(true);
|
|
56
|
-
expect(status.model).toBe(ANTHROPIC_DEFAULT_MODEL);
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
describe("AnthropicOAuthAdapter — redaction invariant", () => {
|
|
61
|
-
it("redacts secrets and records an audit line", async () => {
|
|
62
|
-
const store = makeMemoryStore({ anthropic: seedToken() });
|
|
63
|
-
let capturedBody = "";
|
|
64
|
-
const http = makeStubHttpClient((_url, init) => {
|
|
65
|
-
capturedBody = (init?.body as string) ?? "";
|
|
66
|
-
return jsonResponse({
|
|
67
|
-
content: [{ type: "text", text: "ok" }],
|
|
68
|
-
usage: { input_tokens: 5, output_tokens: 3 },
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
const adapter = new AnthropicOAuthAdapter({
|
|
72
|
-
credentialStore: store,
|
|
73
|
-
projectRoot: tmp,
|
|
74
|
-
endpoints: FAKE_ENDPOINTS,
|
|
75
|
-
httpClient: http,
|
|
76
|
-
skipConsent: true,
|
|
77
|
-
});
|
|
78
|
-
const secret = "ghp_1234567890abcdefghijklmnopqrstuvwxyz";
|
|
79
|
-
const res = await adapter.complete([
|
|
80
|
-
{ role: "user", content: `Investigate token ${secret}.` },
|
|
81
|
-
]);
|
|
82
|
-
expect(res.content).toBe("ok");
|
|
83
|
-
expect(capturedBody).not.toContain(secret);
|
|
84
|
-
expect(capturedBody).toContain("[[REDACTED:");
|
|
85
|
-
const auditPath = path.join(tmp, ".mandu", "brain-redactions.jsonl");
|
|
86
|
-
const contents = await fs.readFile(auditPath, "utf8");
|
|
87
|
-
expect(contents).toContain("anthropic");
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
describe("AnthropicOAuthAdapter — 401 fallback chain", () => {
|
|
92
|
-
it("tries silent refresh then scrubs the token on persistent 401", async () => {
|
|
93
|
-
const store = makeMemoryStore({ anthropic: seedToken() });
|
|
94
|
-
let calls = 0;
|
|
95
|
-
const http = makeStubHttpClient((url) => {
|
|
96
|
-
calls += 1;
|
|
97
|
-
if (url === FAKE_ENDPOINTS.tokenUrl) {
|
|
98
|
-
return jsonResponse({
|
|
99
|
-
access_token: "refreshed",
|
|
100
|
-
refresh_token: "r2",
|
|
101
|
-
expires_in: 3600,
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
return new Response("unauthorized", { status: 401 });
|
|
105
|
-
});
|
|
106
|
-
const adapter = new AnthropicOAuthAdapter({
|
|
107
|
-
credentialStore: store,
|
|
108
|
-
projectRoot: tmp,
|
|
109
|
-
endpoints: FAKE_ENDPOINTS,
|
|
110
|
-
httpClient: http,
|
|
111
|
-
skipConsent: true,
|
|
112
|
-
});
|
|
113
|
-
const res = await adapter.complete([{ role: "user", content: "ping" }]);
|
|
114
|
-
expect(res.content).toBe("");
|
|
115
|
-
expect(calls).toBe(3);
|
|
116
|
-
expect(await store.load("anthropic")).toBeNull();
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
describe("AnthropicOAuthAdapter — system message split", () => {
|
|
121
|
-
it("pulls leading system messages into the `system` field and sends only user/assistant turns in messages[]", async () => {
|
|
122
|
-
const store = makeMemoryStore({ anthropic: seedToken() });
|
|
123
|
-
let capturedBody = "";
|
|
124
|
-
const http = makeStubHttpClient((_url, init) => {
|
|
125
|
-
capturedBody = (init?.body as string) ?? "";
|
|
126
|
-
return jsonResponse({
|
|
127
|
-
content: [{ type: "text", text: "answer" }],
|
|
128
|
-
usage: { input_tokens: 1, output_tokens: 1 },
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
const adapter = new AnthropicOAuthAdapter({
|
|
132
|
-
credentialStore: store,
|
|
133
|
-
projectRoot: tmp,
|
|
134
|
-
endpoints: FAKE_ENDPOINTS,
|
|
135
|
-
httpClient: http,
|
|
136
|
-
skipConsent: true,
|
|
137
|
-
});
|
|
138
|
-
await adapter.complete([
|
|
139
|
-
{ role: "system", content: "You are a helpful assistant." },
|
|
140
|
-
{ role: "user", content: "Hi" },
|
|
141
|
-
]);
|
|
142
|
-
const parsed = JSON.parse(capturedBody);
|
|
143
|
-
expect(parsed.system).toBe("You are a helpful assistant.");
|
|
144
|
-
expect(parsed.messages).toEqual([{ role: "user", content: "Hi" }]);
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
describe("AnthropicOAuthAdapter — telemetryOptOut honored via resolver contract", () => {
|
|
149
|
-
it("returns empty completion when consent is declined (simulates opt-out UX)", async () => {
|
|
150
|
-
const store = makeMemoryStore({ anthropic: seedToken() });
|
|
151
|
-
let dispatched = false;
|
|
152
|
-
const http = makeStubHttpClient(() => {
|
|
153
|
-
dispatched = true;
|
|
154
|
-
return jsonResponse({ content: [{ type: "text", text: "nope" }] });
|
|
155
|
-
});
|
|
156
|
-
const adapter = new AnthropicOAuthAdapter({
|
|
157
|
-
credentialStore: store,
|
|
158
|
-
projectRoot: tmp,
|
|
159
|
-
endpoints: FAKE_ENDPOINTS,
|
|
160
|
-
httpClient: http,
|
|
161
|
-
consentDeps: {
|
|
162
|
-
ask: async () => "N",
|
|
163
|
-
write: () => {},
|
|
164
|
-
env: {} as NodeJS.ProcessEnv,
|
|
165
|
-
},
|
|
166
|
-
});
|
|
167
|
-
const res = await adapter.complete([{ role: "user", content: "hi" }]);
|
|
168
|
-
expect(res.content).toBe("");
|
|
169
|
-
expect(dispatched).toBe(false);
|
|
170
|
-
});
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
describe("AnthropicOAuthAdapter — model override flows into request", () => {
|
|
174
|
-
it("uses overridden model in the outgoing body", async () => {
|
|
175
|
-
const store = makeMemoryStore({ anthropic: seedToken() });
|
|
176
|
-
let capturedBody = "";
|
|
177
|
-
const http = makeStubHttpClient((_url, init) => {
|
|
178
|
-
capturedBody = (init?.body as string) ?? "";
|
|
179
|
-
return jsonResponse({
|
|
180
|
-
content: [{ type: "text", text: "ok" }],
|
|
181
|
-
usage: { input_tokens: 1, output_tokens: 1 },
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
const adapter = new AnthropicOAuthAdapter({
|
|
185
|
-
credentialStore: store,
|
|
186
|
-
projectRoot: tmp,
|
|
187
|
-
endpoints: FAKE_ENDPOINTS,
|
|
188
|
-
httpClient: http,
|
|
189
|
-
skipConsent: true,
|
|
190
|
-
model: "claude-sonnet-4-5-20250929",
|
|
191
|
-
});
|
|
192
|
-
await adapter.complete([{ role: "user", content: "hi" }]);
|
|
193
|
-
const parsed = JSON.parse(capturedBody);
|
|
194
|
-
expect(parsed.model).toBe("claude-sonnet-4-5-20250929");
|
|
195
|
-
});
|
|
196
|
-
});
|
|
1
|
+
/**
|
|
2
|
+
* Tests for `packages/core/src/brain/adapters/anthropic-oauth.ts`.
|
|
3
|
+
*
|
|
4
|
+
* Mirror-image of the OpenAI adapter test file. We reuse the shared
|
|
5
|
+
* in-memory credential store fixture + stub HTTP client, and exercise
|
|
6
|
+
* the Messages-API-specific quirks (system split, 401 refresh,
|
|
7
|
+
* stop_sequences mapping).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, it, expect, beforeEach } from "bun:test";
|
|
11
|
+
import { promises as fs } from "node:fs";
|
|
12
|
+
import os from "node:os";
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
import {
|
|
15
|
+
AnthropicOAuthAdapter,
|
|
16
|
+
ANTHROPIC_DEFAULT_MODEL,
|
|
17
|
+
} from "../anthropic-oauth";
|
|
18
|
+
import {
|
|
19
|
+
makeMemoryStore,
|
|
20
|
+
makeStubHttpClient,
|
|
21
|
+
FAKE_ENDPOINTS,
|
|
22
|
+
jsonResponse,
|
|
23
|
+
} from "./_helpers";
|
|
24
|
+
import type { StoredToken } from "../../credentials";
|
|
25
|
+
|
|
26
|
+
let tmp: string;
|
|
27
|
+
|
|
28
|
+
beforeEach(async () => {
|
|
29
|
+
tmp = await fs.mkdtemp(path.join(os.tmpdir(), "mandu-anthropic-adapter-"));
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
function seedToken(): StoredToken {
|
|
33
|
+
return {
|
|
34
|
+
access_token: "seed-access",
|
|
35
|
+
refresh_token: "seed-refresh",
|
|
36
|
+
expires_at: Math.floor(Date.now() / 1000) + 3600,
|
|
37
|
+
default_model: ANTHROPIC_DEFAULT_MODEL,
|
|
38
|
+
provider: "anthropic",
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
describe("AnthropicOAuthAdapter — shape + defaults", () => {
|
|
43
|
+
it("reports adapter name anthropic-oauth and default Haiku model", async () => {
|
|
44
|
+
const store = makeMemoryStore({ anthropic: seedToken() });
|
|
45
|
+
const adapter = new AnthropicOAuthAdapter({
|
|
46
|
+
credentialStore: store,
|
|
47
|
+
projectRoot: tmp,
|
|
48
|
+
endpoints: FAKE_ENDPOINTS,
|
|
49
|
+
httpClient: makeStubHttpClient(() => jsonResponse({ content: [] })),
|
|
50
|
+
skipConsent: true,
|
|
51
|
+
});
|
|
52
|
+
expect(adapter.name).toBe("anthropic-oauth");
|
|
53
|
+
expect(adapter.model).toBe(ANTHROPIC_DEFAULT_MODEL);
|
|
54
|
+
const status = await adapter.checkStatus();
|
|
55
|
+
expect(status.available).toBe(true);
|
|
56
|
+
expect(status.model).toBe(ANTHROPIC_DEFAULT_MODEL);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
describe("AnthropicOAuthAdapter — redaction invariant", () => {
|
|
61
|
+
it("redacts secrets and records an audit line", async () => {
|
|
62
|
+
const store = makeMemoryStore({ anthropic: seedToken() });
|
|
63
|
+
let capturedBody = "";
|
|
64
|
+
const http = makeStubHttpClient((_url, init) => {
|
|
65
|
+
capturedBody = (init?.body as string) ?? "";
|
|
66
|
+
return jsonResponse({
|
|
67
|
+
content: [{ type: "text", text: "ok" }],
|
|
68
|
+
usage: { input_tokens: 5, output_tokens: 3 },
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
const adapter = new AnthropicOAuthAdapter({
|
|
72
|
+
credentialStore: store,
|
|
73
|
+
projectRoot: tmp,
|
|
74
|
+
endpoints: FAKE_ENDPOINTS,
|
|
75
|
+
httpClient: http,
|
|
76
|
+
skipConsent: true,
|
|
77
|
+
});
|
|
78
|
+
const secret = "ghp_1234567890abcdefghijklmnopqrstuvwxyz";
|
|
79
|
+
const res = await adapter.complete([
|
|
80
|
+
{ role: "user", content: `Investigate token ${secret}.` },
|
|
81
|
+
]);
|
|
82
|
+
expect(res.content).toBe("ok");
|
|
83
|
+
expect(capturedBody).not.toContain(secret);
|
|
84
|
+
expect(capturedBody).toContain("[[REDACTED:");
|
|
85
|
+
const auditPath = path.join(tmp, ".mandu", "brain-redactions.jsonl");
|
|
86
|
+
const contents = await fs.readFile(auditPath, "utf8");
|
|
87
|
+
expect(contents).toContain("anthropic");
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe("AnthropicOAuthAdapter — 401 fallback chain", () => {
|
|
92
|
+
it("tries silent refresh then scrubs the token on persistent 401", async () => {
|
|
93
|
+
const store = makeMemoryStore({ anthropic: seedToken() });
|
|
94
|
+
let calls = 0;
|
|
95
|
+
const http = makeStubHttpClient((url) => {
|
|
96
|
+
calls += 1;
|
|
97
|
+
if (url === FAKE_ENDPOINTS.tokenUrl) {
|
|
98
|
+
return jsonResponse({
|
|
99
|
+
access_token: "refreshed",
|
|
100
|
+
refresh_token: "r2",
|
|
101
|
+
expires_in: 3600,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
return new Response("unauthorized", { status: 401 });
|
|
105
|
+
});
|
|
106
|
+
const adapter = new AnthropicOAuthAdapter({
|
|
107
|
+
credentialStore: store,
|
|
108
|
+
projectRoot: tmp,
|
|
109
|
+
endpoints: FAKE_ENDPOINTS,
|
|
110
|
+
httpClient: http,
|
|
111
|
+
skipConsent: true,
|
|
112
|
+
});
|
|
113
|
+
const res = await adapter.complete([{ role: "user", content: "ping" }]);
|
|
114
|
+
expect(res.content).toBe("");
|
|
115
|
+
expect(calls).toBe(3);
|
|
116
|
+
expect(await store.load("anthropic")).toBeNull();
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
describe("AnthropicOAuthAdapter — system message split", () => {
|
|
121
|
+
it("pulls leading system messages into the `system` field and sends only user/assistant turns in messages[]", async () => {
|
|
122
|
+
const store = makeMemoryStore({ anthropic: seedToken() });
|
|
123
|
+
let capturedBody = "";
|
|
124
|
+
const http = makeStubHttpClient((_url, init) => {
|
|
125
|
+
capturedBody = (init?.body as string) ?? "";
|
|
126
|
+
return jsonResponse({
|
|
127
|
+
content: [{ type: "text", text: "answer" }],
|
|
128
|
+
usage: { input_tokens: 1, output_tokens: 1 },
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
const adapter = new AnthropicOAuthAdapter({
|
|
132
|
+
credentialStore: store,
|
|
133
|
+
projectRoot: tmp,
|
|
134
|
+
endpoints: FAKE_ENDPOINTS,
|
|
135
|
+
httpClient: http,
|
|
136
|
+
skipConsent: true,
|
|
137
|
+
});
|
|
138
|
+
await adapter.complete([
|
|
139
|
+
{ role: "system", content: "You are a helpful assistant." },
|
|
140
|
+
{ role: "user", content: "Hi" },
|
|
141
|
+
]);
|
|
142
|
+
const parsed = JSON.parse(capturedBody);
|
|
143
|
+
expect(parsed.system).toBe("You are a helpful assistant.");
|
|
144
|
+
expect(parsed.messages).toEqual([{ role: "user", content: "Hi" }]);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe("AnthropicOAuthAdapter — telemetryOptOut honored via resolver contract", () => {
|
|
149
|
+
it("returns empty completion when consent is declined (simulates opt-out UX)", async () => {
|
|
150
|
+
const store = makeMemoryStore({ anthropic: seedToken() });
|
|
151
|
+
let dispatched = false;
|
|
152
|
+
const http = makeStubHttpClient(() => {
|
|
153
|
+
dispatched = true;
|
|
154
|
+
return jsonResponse({ content: [{ type: "text", text: "nope" }] });
|
|
155
|
+
});
|
|
156
|
+
const adapter = new AnthropicOAuthAdapter({
|
|
157
|
+
credentialStore: store,
|
|
158
|
+
projectRoot: tmp,
|
|
159
|
+
endpoints: FAKE_ENDPOINTS,
|
|
160
|
+
httpClient: http,
|
|
161
|
+
consentDeps: {
|
|
162
|
+
ask: async () => "N",
|
|
163
|
+
write: () => {},
|
|
164
|
+
env: {} as NodeJS.ProcessEnv,
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
const res = await adapter.complete([{ role: "user", content: "hi" }]);
|
|
168
|
+
expect(res.content).toBe("");
|
|
169
|
+
expect(dispatched).toBe(false);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
describe("AnthropicOAuthAdapter — model override flows into request", () => {
|
|
174
|
+
it("uses overridden model in the outgoing body", async () => {
|
|
175
|
+
const store = makeMemoryStore({ anthropic: seedToken() });
|
|
176
|
+
let capturedBody = "";
|
|
177
|
+
const http = makeStubHttpClient((_url, init) => {
|
|
178
|
+
capturedBody = (init?.body as string) ?? "";
|
|
179
|
+
return jsonResponse({
|
|
180
|
+
content: [{ type: "text", text: "ok" }],
|
|
181
|
+
usage: { input_tokens: 1, output_tokens: 1 },
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
const adapter = new AnthropicOAuthAdapter({
|
|
185
|
+
credentialStore: store,
|
|
186
|
+
projectRoot: tmp,
|
|
187
|
+
endpoints: FAKE_ENDPOINTS,
|
|
188
|
+
httpClient: http,
|
|
189
|
+
skipConsent: true,
|
|
190
|
+
model: "claude-sonnet-4-5-20250929",
|
|
191
|
+
});
|
|
192
|
+
await adapter.complete([{ role: "user", content: "hi" }]);
|
|
193
|
+
const parsed = JSON.parse(capturedBody);
|
|
194
|
+
expect(parsed.model).toBe("claude-sonnet-4-5-20250929");
|
|
195
|
+
});
|
|
196
|
+
});
|