@cartanova/qgrid-cli 2.10.9 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/dist/_virtual/_rolldown/runtime.js +1 -10
- package/bundle/dist/application/monit/log-buffer.js +12 -6
- package/bundle/dist/application/monit/monit.frame.js +11 -3
- package/bundle/dist/application/monit/monit.types.js +1 -1
- package/bundle/dist/application/qgrid/conv-routing.js +9 -6
- package/bundle/dist/application/qgrid/expired-token-reminder.js +2 -2
- package/bundle/dist/application/qgrid/oauth.js +31 -4
- package/bundle/dist/application/qgrid/qgrid-image-generation.js +1 -1
- package/bundle/dist/application/qgrid/qgrid-response-format.js +22 -20
- package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +43 -34
- package/bundle/dist/application/qgrid/qgrid.dispatcher.js +128 -93
- package/bundle/dist/application/qgrid/qgrid.frame.js +930 -49
- package/bundle/dist/application/qgrid/qgrid.types.js +212 -5
- package/bundle/dist/application/qgrid/schema-prompt.js +75 -48
- package/bundle/dist/application/qgrid/slack-user-map.js +1 -1
- package/bundle/dist/application/qgrid/token-death.js +1 -1
- package/bundle/dist/application/qgrid/token-subscriber.js +83 -30
- package/bundle/dist/application/qgrid/token-trigger-setup.js +1 -1
- package/bundle/dist/application/qgrid/token-window-keepalive.js +8 -6
- package/bundle/dist/application/qgrid/tool-emulation-schema.js +13 -13
- package/bundle/dist/application/qgrid/tool-emulation.js +19 -15
- package/bundle/dist/application/request-log/json-schema-type-text.js +29 -12
- package/bundle/dist/application/request-log/request-log.model.js +83 -69
- package/bundle/dist/application/request-log/request-log.types.js +8 -2
- package/bundle/dist/application/request-log/zod-code-format.js +1 -1
- package/bundle/dist/application/request-log-step/request-log-step.model.js +1 -1
- package/bundle/dist/application/request-log-step/request-log-step.types.js +1 -1
- package/bundle/dist/application/setting/setting.constant.js +1 -1
- package/bundle/dist/application/setting/setting.model.js +2 -2
- package/bundle/dist/application/setting/setting.store.js +2 -2
- package/bundle/dist/application/setting/setting.types.js +1 -1
- package/bundle/dist/application/sonamu.generated.js +40 -16
- package/bundle/dist/application/sonamu.generated.sso.js +2 -1
- package/bundle/dist/application/token/token.model.js +26 -9
- package/bundle/dist/application/token/token.types.js +20 -3
- package/bundle/dist/i18n/en.js +15 -1
- package/bundle/dist/i18n/ko.js +15 -1
- package/bundle/dist/i18n/sd.generated.js +2 -1
- package/bundle/dist/migrations/20260807133553_manual__backfill_request_log_cost.js +8 -6
- package/bundle/dist/migrations/20261018215031_alter_request_logs_add1_alter1.js +15 -0
- package/bundle/dist/server-bootstrap.js +4 -2
- package/bundle/dist/server-error-handler.js +1 -1
- package/bundle/dist/sonamu.config.js +37 -8
- package/bundle/dist/startup-migrations.js +17 -7
- package/bundle/dist/testing/global.js +1 -1
- package/bundle/dist/testing/schema-bench.js +0 -0
- package/bundle/dist/testing/test-database-name.js +1 -1
- package/bundle/dist/utils/providers/anthropic/anthropic-constants.js +1 -1
- package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +11 -5
- package/bundle/dist/utils/providers/anthropic/anthropic-quota.js +4 -4
- package/bundle/dist/utils/providers/anthropic/anthropic-thinking.js +1 -1
- package/bundle/dist/utils/providers/anthropic/claude-session.js +20 -19
- package/bundle/dist/utils/providers/anthropic/fence-strip.js +1 -1
- package/bundle/dist/utils/providers/anthropic/stream-json-adapter.js +49 -23
- package/bundle/dist/utils/providers/common/credentials.js +5 -1
- package/bundle/dist/utils/providers/common/effort.js +3 -3
- package/bundle/dist/utils/providers/common/model-cost.js +69 -14
- package/bundle/dist/utils/providers/common/provider-types.js +29 -1
- package/bundle/dist/utils/providers/common/schema-validation.js +78 -40
- package/bundle/dist/utils/providers/common/smooth-weighted-round-robin.js +1 -1
- package/bundle/dist/utils/providers/common/strictifier.js +62 -43
- package/bundle/dist/utils/providers/common/thinking.js +3 -2
- package/bundle/dist/utils/providers/common/ttft.js +1 -1
- package/bundle/dist/utils/providers/grok/grok-backend-protocol.js +427 -0
- package/bundle/dist/utils/providers/grok/grok-constants.js +55 -0
- package/bundle/dist/utils/providers/grok/grok-direct-client.js +196 -0
- package/bundle/dist/utils/providers/grok/grok-dispatcher.js +1313 -0
- package/bundle/dist/utils/providers/grok/grok-headers.js +118 -0
- package/bundle/dist/utils/providers/grok/grok-media-client.js +420 -0
- package/bundle/dist/utils/providers/grok/grok-models.js +114 -0
- package/bundle/dist/utils/providers/grok/grok-oauth.js +455 -0
- package/bundle/dist/utils/providers/grok/grok-quota.js +119 -0
- package/bundle/dist/utils/providers/grok/grok-refresh.js +192 -0
- package/bundle/dist/utils/providers/grok/grok-types.js +186 -0
- package/bundle/dist/utils/providers/grok/grok-voice-client.js +199 -0
- package/bundle/dist/utils/providers/grok/index.js +11 -0
- package/bundle/dist/utils/providers/openai/openai-backend-protocol.js +111 -83
- package/bundle/dist/utils/providers/openai/openai-callback-relay.js +3 -2
- package/bundle/dist/utils/providers/openai/openai-constants.js +1 -1
- package/bundle/dist/utils/providers/openai/openai-direct-client.js +23 -7
- package/bundle/dist/utils/providers/openai/openai-dispatcher.js +143 -106
- package/bundle/dist/utils/providers/openai/openai-image-generation.js +48 -33
- package/bundle/dist/utils/providers/openai/openai-oauth.js +28 -13
- package/bundle/dist/utils/providers/openai/openai-quota.js +38 -27
- package/bundle/dist/utils/providers/openai/openai-refresh.js +17 -9
- package/bundle/dist/utils/providers/openai/openai-sse.js +1 -1
- package/bundle/dist/utils/providers/openai/openai-transport-config.js +1 -1
- package/bundle/dist/utils/quiet-hours.js +1 -1
- package/bundle/dist/utils/slack-notify.js +14 -8
- package/bundle/dist/utils/subset-loaders.js +4 -5
- package/bundle/src/application/monit/log-buffer.ts +23 -9
- package/bundle/src/application/monit/monit.frame.ts +22 -5
- package/bundle/src/application/monit/monit.types.ts +6 -0
- package/bundle/src/application/qgrid/conv-routing.test.ts +76 -4
- package/bundle/src/application/qgrid/conv-routing.ts +35 -9
- package/bundle/src/application/qgrid/expired-token-reminder.ts +9 -1
- package/bundle/src/application/qgrid/oauth.ts +51 -15
- package/bundle/src/application/qgrid/qgrid-image-generation.ts +9 -0
- package/bundle/src/application/qgrid/qgrid-response-format.ts +50 -25
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +33 -0
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +87 -40
- package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +97 -0
- package/bundle/src/application/qgrid/qgrid.dispatcher.ts +274 -126
- package/bundle/src/application/qgrid/qgrid.frame.test.ts +1013 -3
- package/bundle/src/application/qgrid/qgrid.frame.ts +1415 -60
- package/bundle/src/application/qgrid/qgrid.types.ts +335 -0
- package/bundle/src/application/qgrid/schema-prompt.ts +105 -41
- package/bundle/src/application/qgrid/slack-user-map.ts +5 -0
- package/bundle/src/application/qgrid/token-death.ts +4 -0
- package/bundle/src/application/qgrid/token-subscriber.test.ts +21 -19
- package/bundle/src/application/qgrid/token-subscriber.ts +186 -53
- package/bundle/src/application/qgrid/token-trigger-setup.ts +2 -0
- package/bundle/src/application/qgrid/token-window-keepalive.ts +49 -6
- package/bundle/src/application/qgrid/tool-emulation-schema.ts +33 -29
- package/bundle/src/application/qgrid/tool-emulation.ts +52 -27
- package/bundle/src/application/request-log/json-schema-type-text.test.ts +5 -5
- package/bundle/src/application/request-log/json-schema-type-text.ts +81 -26
- package/bundle/src/application/request-log/request-log.entity.json +8 -0
- package/bundle/src/application/request-log/request-log.model.test.ts +111 -4
- package/bundle/src/application/request-log/request-log.model.ts +279 -145
- package/bundle/src/application/request-log/request-log.types.ts +17 -0
- package/bundle/src/application/request-log/zod-code-format.ts +11 -0
- package/bundle/src/application/request-log-step/request-log-step.model.ts +1 -0
- package/bundle/src/application/request-log-step/request-log-step.types.ts +2 -0
- package/bundle/src/application/setting/setting.constant.ts +9 -0
- package/bundle/src/application/setting/setting.model.ts +12 -2
- package/bundle/src/application/setting/setting.store.ts +5 -1
- package/bundle/src/application/setting/setting.types.ts +8 -0
- package/bundle/src/application/sonamu.generated.http +135 -0
- package/bundle/src/application/sonamu.generated.sso.ts +3 -0
- package/bundle/src/application/sonamu.generated.ts +29 -0
- package/bundle/src/application/token/token.identity.test.ts +20 -0
- package/bundle/src/application/token/token.model.ts +66 -7
- package/bundle/src/application/token/token.types.ts +24 -1
- package/bundle/src/i18n/en.ts +19 -0
- package/bundle/src/i18n/ko.ts +21 -0
- package/bundle/src/i18n/sd.generated.ts +24 -2
- package/bundle/src/migrations/20260807133553_manual__backfill_request_log_cost.ts +16 -8
- package/bundle/src/migrations/20261018215031_alter_request_logs_add1_alter1.ts +15 -0
- package/bundle/src/server-bootstrap.ts +4 -2
- package/bundle/src/server-error-handler.ts +1 -0
- package/bundle/src/sonamu.config.ts +69 -7
- package/bundle/src/startup-migrations.ts +27 -9
- package/bundle/src/testing/global.ts +20 -0
- package/bundle/src/testing/schema-bench.ts +105 -30
- package/bundle/src/testing/test-database-name.ts +2 -0
- package/bundle/src/utils/providers/anthropic/anthropic-constants.ts +8 -0
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +41 -6
- package/bundle/src/utils/providers/anthropic/anthropic-quota.ts +7 -3
- package/bundle/src/utils/providers/anthropic/anthropic-thinking.ts +6 -0
- package/bundle/src/utils/providers/anthropic/claude-session.ts +58 -24
- package/bundle/src/utils/providers/anthropic/fence-strip.ts +11 -0
- package/bundle/src/utils/providers/anthropic/stream-json-adapter.ts +110 -45
- package/bundle/src/utils/providers/common/credentials.ts +8 -0
- package/bundle/src/utils/providers/common/effort.ts +9 -2
- package/bundle/src/utils/providers/common/model-cost.test.ts +48 -1
- package/bundle/src/utils/providers/common/model-cost.ts +259 -158
- package/bundle/src/utils/providers/common/provider-dispatcher.ts +98 -2
- package/bundle/src/utils/providers/common/provider-types.ts +46 -3
- package/bundle/src/utils/providers/common/schema-validation.test.ts +5 -1
- package/bundle/src/utils/providers/common/schema-validation.ts +124 -56
- package/bundle/src/utils/providers/common/smooth-weighted-round-robin.ts +4 -0
- package/bundle/src/utils/providers/common/strictifier.ts +185 -59
- package/bundle/src/utils/providers/common/thinking.ts +2 -2
- package/bundle/src/utils/providers/common/ttft.ts +4 -2
- package/bundle/src/utils/providers/grok/__fixtures__/golden-responses-1.0.60.json +164 -0
- package/bundle/src/utils/providers/grok/grok-backend-protocol.test.ts +325 -0
- package/bundle/src/utils/providers/grok/grok-backend-protocol.ts +721 -0
- package/bundle/src/utils/providers/grok/grok-constants.ts +105 -0
- package/bundle/src/utils/providers/grok/grok-direct-client.test.ts +179 -0
- package/bundle/src/utils/providers/grok/grok-direct-client.ts +313 -0
- package/bundle/src/utils/providers/grok/grok-dispatcher.test.ts +1395 -0
- package/bundle/src/utils/providers/grok/grok-dispatcher.ts +2105 -0
- package/bundle/src/utils/providers/grok/grok-headers.test.ts +149 -0
- package/bundle/src/utils/providers/grok/grok-headers.ts +199 -0
- package/bundle/src/utils/providers/grok/grok-media-client.test.ts +446 -0
- package/bundle/src/utils/providers/grok/grok-media-client.ts +703 -0
- package/bundle/src/utils/providers/grok/grok-models.test.ts +96 -0
- package/bundle/src/utils/providers/grok/grok-models.ts +161 -0
- package/bundle/src/utils/providers/grok/grok-oauth.test.ts +406 -0
- package/bundle/src/utils/providers/grok/grok-oauth.ts +771 -0
- package/bundle/src/utils/providers/grok/grok-quota.test.ts +142 -0
- package/bundle/src/utils/providers/grok/grok-quota.ts +198 -0
- package/bundle/src/utils/providers/grok/grok-refresh.test.ts +239 -0
- package/bundle/src/utils/providers/grok/grok-refresh.ts +325 -0
- package/bundle/src/utils/providers/grok/grok-types.test.ts +252 -0
- package/bundle/src/utils/providers/grok/grok-types.ts +374 -0
- package/bundle/src/utils/providers/grok/grok-voice-client.test.ts +321 -0
- package/bundle/src/utils/providers/grok/grok-voice-client.ts +284 -0
- package/bundle/src/utils/providers/grok/index.ts +20 -0
- package/bundle/src/utils/providers/openai/openai-backend-protocol.ts +221 -137
- package/bundle/src/utils/providers/openai/openai-callback-relay.ts +12 -1
- package/bundle/src/utils/providers/openai/openai-constants.ts +2 -0
- package/bundle/src/utils/providers/openai/openai-direct-client.ts +111 -21
- package/bundle/src/utils/providers/openai/openai-dispatcher.ts +322 -169
- package/bundle/src/utils/providers/openai/openai-image-generation.ts +116 -36
- package/bundle/src/utils/providers/openai/openai-oauth.ts +48 -20
- package/bundle/src/utils/providers/openai/openai-quota.ts +77 -46
- package/bundle/src/utils/providers/openai/openai-refresh.ts +42 -18
- package/bundle/src/utils/providers/openai/openai-sse.ts +27 -3
- package/bundle/src/utils/providers/openai/openai-transport-config.ts +2 -0
- package/bundle/src/utils/quiet-hours.ts +12 -1
- package/bundle/src/utils/slack-notify.ts +44 -13
- package/bundle/src/utils/subset-loaders.ts +7 -7
- package/bundle/web-dist/client/assets/clsx-5XM_pHvN.js +1 -0
- package/bundle/web-dist/client/assets/index-BA7uQ-6c.js +31 -0
- package/bundle/web-dist/client/assets/index-Be2qCZmI.css +1 -0
- package/bundle/web-dist/client/assets/logs-C47OJGEI.js +1 -0
- package/bundle/web-dist/client/assets/monit-BS9no0dU.js +4 -0
- package/bundle/web-dist/client/assets/plus-sdACTfH0.js +1 -0
- package/bundle/web-dist/client/assets/refresh-cw-CY8o_1cT.js +1 -0
- package/bundle/web-dist/client/assets/request-model-BRtFuZvj.js +1 -0
- package/bundle/web-dist/client/assets/routes-kqgkUxE8.js +5 -0
- package/bundle/web-dist/client/assets/{services.generated-BsieU37H.js → services.generated-CefiDXEv.js} +5 -5
- package/bundle/web-dist/client/assets/settings-DNDvFGSw.js +1 -0
- package/bundle/web-dist/client/assets/show-u8Np69q3.js +2 -0
- package/bundle/web-dist/client/assets/tokens-QvP410NW.js +1 -0
- package/bundle/web-dist/client/assets/total-cost-MnfKU8IN.js +1 -0
- package/bundle/web-dist/client/assets/use-oauth-login-flow-Bzdh28Ws.js +1 -0
- package/bundle/web-dist/client/assets/use-update-token-mutation-CfJKaxmR.js +1 -0
- package/bundle/web-dist/client/assets/vendor-react-CUFFrVN9.js +244 -0
- package/bundle/web-dist/client/assets/vendor-tanstack-Bf_jag9G.js +1 -0
- package/bundle/web-dist/client/index.html +6 -6
- package/bundle/web-dist/server/assets/clsx-D_N5PN_2.js +16 -0
- package/bundle/web-dist/server/assets/{lazyRouteComponent-Dtd0NR4r.js → lazyRouteComponent-D8iTIHyn.js} +129 -2
- package/bundle/web-dist/server/assets/logs-B3OTd9hy.js +825 -0
- package/bundle/web-dist/server/assets/{monit-DvzribSE.js → monit-B2hqorPe.js} +385 -126
- package/bundle/web-dist/server/assets/plus-DwG7h9kq.js +28 -0
- package/bundle/web-dist/server/assets/{react-dom-B4a6-uuR.js → react-dom-BIYQzBqG.js} +2 -129
- package/bundle/web-dist/server/assets/refresh-cw-mMBkwOq0.js +44 -0
- package/bundle/web-dist/server/assets/{request-model-CbqfnQOJ.js → request-model-I6OdODSH.js} +15 -6
- package/bundle/web-dist/server/assets/{routes-BAPWTizT.js → routes-B95YlUv2.js} +760 -213
- package/bundle/web-dist/server/assets/{services.generated-CEbGjsI0.js → services.generated-DQATJ6qf.js} +12821 -12194
- package/bundle/web-dist/server/assets/settings-C3gbGk0m.js +830 -0
- package/bundle/web-dist/server/assets/{show-CxVZTAdv.js → show-Bxaj3rhH.js} +1355 -419
- package/bundle/web-dist/server/assets/tokens-CZjH3cB7.js +1038 -0
- package/bundle/web-dist/server/assets/total-cost-fTE9Xy82.js +18 -0
- package/bundle/web-dist/server/assets/use-oauth-login-flow-CKDHgc3U.js +2379 -0
- package/bundle/web-dist/server/assets/{use-update-token-mutation-CfYmk_4_.js → use-update-token-mutation-BEbgOzaa.js} +1 -1
- package/bundle/web-dist/server/entry-server.generated.js +4303 -22810
- package/dist/cli.js +9 -9
- package/package.json +4 -11
- package/postinstall.mjs +12 -0
- package/skills/qgrid/SKILL.md +1 -0
- package/skills/qgrid/references/cli-env-and-server-boot.md +4 -1
- package/skills/qgrid/references/decision-rationale.md +24 -1
- package/skills/qgrid/references/grok-runtime.md +89 -0
- package/skills/qgrid/references/provider-runtime-differences.md +30 -29
- package/skills/qgrid/references/repo-map.md +10 -0
- package/skills/qgrid/references/request-log-run-lifecycle.md +1 -1
- package/skills/qgrid/references/sonamu-api-web-flow.md +1 -1
- package/skills/qgrid/references/token-auth-quota-lifecycle.md +56 -3
- package/bundle/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +0 -406
- package/bundle/dist/node_modules/.pnpm/@vitest_expect@4.1.10/node_modules/@vitest/expect/dist/index.js +0 -1507
- package/bundle/dist/node_modules/.pnpm/@vitest_pretty-format@4.1.10/node_modules/@vitest/pretty-format/dist/index.js +0 -887
- package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/chunk-artifact.js +0 -2756
- package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/index.js +0 -8
- package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/utils.js +0 -8
- package/bundle/dist/node_modules/.pnpm/@vitest_snapshot@4.1.10/node_modules/@vitest/snapshot/dist/index.js +0 -922
- package/bundle/dist/node_modules/.pnpm/@vitest_spy@4.1.10/node_modules/@vitest/spy/dist/index.js +0 -386
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +0 -121
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/constants.js +0 -51
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/diff.js +0 -1317
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/display.js +0 -561
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/error.js +0 -40
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/helpers.js +0 -272
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/offset.js +0 -27
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/serialize.js +0 -77
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/source-map.js +0 -381
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/timers.js +0 -51
- package/bundle/dist/node_modules/.pnpm/chai@6.2.2/node_modules/chai/index.js +0 -2986
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/branding.js +0 -10
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/index.js +0 -109
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/messages.js +0 -10
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/overloads.js +0 -10
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/utils.js +0 -10
- package/bundle/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js +0 -1126
- package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.js +0 -21
- package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js +0 -432
- package/bundle/dist/node_modules/.pnpm/tinybench@2.9.0/node_modules/tinybench/dist/index.js +0 -517
- package/bundle/dist/node_modules/.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js +0 -101
- package/bundle/dist/node_modules/.pnpm/vite@8.0.3_@emnapi_core@1.11.2_@emnapi_runtime@1.11.2_@types_node@25.0.7_esbuild@0.27.4_5b35fc1fb85d2af4d105e0d74f940f50/node_modules/vite/dist/node/module-runner.js +0 -1265
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.js +0 -9
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/benchmark.CX_oY03V.js +0 -41
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/evaluatedModules.Dg1zASAC.js +0 -19
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/index.Chj8NDwU.js +0 -202
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/index.DdgEv5B1.js +0 -46
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/rpc.MzXet3jl.js +0 -119
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/test.DNmyFkvJ.js +0 -3044
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.js +0 -59
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/index.js +0 -28
- package/bundle/dist/testing/setup-mocks.js +0 -16
- package/bundle/src/testing/setup-mocks.ts +0 -44
- package/bundle/web-dist/client/assets/index-Bw2s88Ot.css +0 -1
- package/bundle/web-dist/client/assets/index-CrXKu_J8.js +0 -106
- package/bundle/web-dist/client/assets/logs-B2SmWJXA.js +0 -1
- package/bundle/web-dist/client/assets/monit-D-JwXXoA.js +0 -1
- package/bundle/web-dist/client/assets/plus-B62CuqT8.js +0 -1
- package/bundle/web-dist/client/assets/refresh-cw-NNcU0Cmq.js +0 -1
- package/bundle/web-dist/client/assets/request-model-CojtinqK.js +0 -1
- package/bundle/web-dist/client/assets/routes-C5r4gTvY.js +0 -5
- package/bundle/web-dist/client/assets/settings-D3tDSAck.js +0 -1
- package/bundle/web-dist/client/assets/show-Cah_kUKC.js +0 -2
- package/bundle/web-dist/client/assets/tokens-DU2Iyxxd.js +0 -1
- package/bundle/web-dist/client/assets/use-oauth-login-flow-D0UaR9_e.js +0 -1
- package/bundle/web-dist/client/assets/use-update-token-mutation-DAq0F8p-.js +0 -1
- package/bundle/web-dist/client/assets/vendor-react-DH4kUfK2.js +0 -9
- package/bundle/web-dist/client/assets/vendor-tanstack-DJRQAbrY.js +0 -1
- package/bundle/web-dist/server/assets/logs-l91avYif.js +0 -509
- package/bundle/web-dist/server/assets/plus-KZrECewT.js +0 -19
- package/bundle/web-dist/server/assets/refresh-cw-BND93JrF.js +0 -23
- package/bundle/web-dist/server/assets/settings-BZR5HSAL.js +0 -461
- package/bundle/web-dist/server/assets/tokens-D1hb4eKk.js +0 -448
- package/bundle/web-dist/server/assets/use-oauth-login-flow-Cvdy0zF8.js +0 -178
- package/dist/cli.d.ts +0 -10
- /package/bundle/web-dist/client/assets/{cost-DH2jZbrw.js → cost-DB3HbU7T.js} +0 -0
- /package/bundle/web-dist/client/assets/{preload-helper-ca-nBW7U.js → preload-helper-DWTEM3RW.js} +0 -0
- /package/bundle/web-dist/server/assets/{cost-eEHeTRT5.js → cost-BC9yzyA9.js} +0 -0
|
@@ -11,12 +11,16 @@
|
|
|
11
11
|
// claude-api 스킬 확인: Sonnet 4.6 official id = "claude-sonnet-4-6" (날짜 suffix 없음).
|
|
12
12
|
// model-cost 테이블에도 "claude-sonnet-4-6" 키 존재
|
|
13
13
|
export const ANTHROPIC_DEFAULT_MODEL = "claude-sonnet-4-6";
|
|
14
|
+
|
|
14
15
|
// OpenAI provider 기본값(openai-dispatcher DEFAULT_EFFORT)과 맞춘다. 클라가 effort 미지정 시 안전망.
|
|
15
16
|
export const ANTHROPIC_DEFAULT_EFFORT = "low";
|
|
17
|
+
|
|
16
18
|
// project scope cwd (settings.json 격리). 토큰별 격리는 CLAUDE_CONFIG_DIR 로 한다.
|
|
17
19
|
export const ANTHROPIC_CLAUDE_CWD = "/tmp/qgrid-anthropic";
|
|
20
|
+
|
|
18
21
|
// per-token CLAUDE_CONFIG_DIR 의 베이스. 실제 경로는 `${BASE}/${tokenId}` (R10 격리).
|
|
19
22
|
export const ANTHROPIC_CONFIG_DIR_BASE = "/tmp/qgrid-anthropic-config";
|
|
23
|
+
|
|
20
24
|
// CC 가 자동 활성화하는 deferred 도구 — 토큰 최적화 위해 dispatcher 경로에서 차단.
|
|
21
25
|
export const ANTHROPIC_DISALLOWED_TOOLS = ["Monitor", "PushNotification", "RemoteTrigger"] as const;
|
|
22
26
|
const ONE_MILLION_SUFFIX_RE = /\[1m\]$/i;
|
|
@@ -35,6 +39,7 @@ export function anthropicConfigDir(tokenId: number): string {
|
|
|
35
39
|
export function canonicalAnthropicModel(model?: string): string {
|
|
36
40
|
const raw = model || ANTHROPIC_DEFAULT_MODEL;
|
|
37
41
|
const withoutProvider = raw.includes("/") ? raw.split("/").pop()! : raw;
|
|
42
|
+
|
|
38
43
|
return withoutProvider.replace(ONE_MILLION_SUFFIX_RE, "");
|
|
39
44
|
}
|
|
40
45
|
|
|
@@ -58,6 +63,7 @@ const ONE_MILLION_CONTEXT_MODELS = new Set([
|
|
|
58
63
|
]);
|
|
59
64
|
|
|
60
65
|
const CLI_ONE_MILLION_SUFFIX_MODELS = new Set(["claude-sonnet-4-6", "claude-opus-4-6"]);
|
|
66
|
+
|
|
61
67
|
// Preserve these defaults when thinking is omitted. This is not an off-capability list:
|
|
62
68
|
// explicit false supports Opus 5, and native extra-body delivery supports Haiku 5.5
|
|
63
69
|
// (disabled) and Sonnet 5.5 (between_tools). See anthropic-thinking.ts.
|
|
@@ -84,6 +90,7 @@ for (const model of CLI_ONE_MILLION_SUFFIX_MODELS) {
|
|
|
84
90
|
throw new Error(`[invariant] CLI 1M suffix model not in context set: ${model}`);
|
|
85
91
|
}
|
|
86
92
|
}
|
|
93
|
+
|
|
87
94
|
// Fable 계열은 공식 사양상 1M 기본 컨텍스트 + adaptive thinking 필수다. 새 Fable 버전을 계열 Set
|
|
88
95
|
// 에만 넣고 나머지를 빠뜨리는 실수를 같은 방식으로 모듈 로드 시점에 잡는다.
|
|
89
96
|
for (const model of FABLE_FAMILY_MODELS) {
|
|
@@ -114,6 +121,7 @@ export function isFableFamilyModel(model?: string): boolean {
|
|
|
114
121
|
export function assertSupportedOneMillionSuffix(model?: string): void {
|
|
115
122
|
if (!hasOneMillionSuffix(model)) return;
|
|
116
123
|
const canonical = canonicalAnthropicModel(model);
|
|
124
|
+
|
|
117
125
|
if (!supports1MContext(canonical)) {
|
|
118
126
|
throw new Error(`Unsupported Anthropic 1M model suffix: ${model}`);
|
|
119
127
|
}
|
|
@@ -7,7 +7,7 @@ import { getLogger } from "@logtape/logtape";
|
|
|
7
7
|
|
|
8
8
|
import { QuotaThresholdExceededError } from "../../../application/qgrid/qgrid.types";
|
|
9
9
|
import { TokenModel } from "../../../application/token/token.model";
|
|
10
|
-
import {
|
|
10
|
+
import { AnthropicCredentials } from "../../../application/token/token.types";
|
|
11
11
|
import { getExpiresAt, getRefreshToken } from "../common/credentials";
|
|
12
12
|
import {
|
|
13
13
|
type GenerateRequest,
|
|
@@ -45,10 +45,18 @@ export class AnthropicDispatcher implements ProviderDispatcher {
|
|
|
45
45
|
// NOTIFY는 기존 토큰을 재전송하지 않으므로 시작 시 DB에서 읽는다.
|
|
46
46
|
const tokens = await TokenModel.findActiveByProvider("A", "anthropic");
|
|
47
47
|
tokens.forEach((t) => {
|
|
48
|
+
const credentials = AnthropicCredentials.safeParse(t.credentials);
|
|
49
|
+
|
|
50
|
+
if (!credentials.success) {
|
|
51
|
+
logger.warn(`skipping token ${t.name}: credentials are not Anthropic OAuth credentials`);
|
|
52
|
+
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
48
56
|
this.tokenPool.set(t.id, {
|
|
49
57
|
id: t.id,
|
|
50
58
|
name: t.name,
|
|
51
|
-
credentials:
|
|
59
|
+
credentials: credentials.data,
|
|
52
60
|
quotaThreshold: t.quota_threshold,
|
|
53
61
|
weight: t.weight,
|
|
54
62
|
});
|
|
@@ -121,13 +129,16 @@ export class AnthropicDispatcher implements ProviderDispatcher {
|
|
|
121
129
|
async selectToken(model: string, preferredTokenId?: number): Promise<PooledToken | null> {
|
|
122
130
|
const preferred =
|
|
123
131
|
preferredTokenId === undefined ? undefined : this.tokenPool.get(preferredTokenId);
|
|
132
|
+
|
|
124
133
|
if (preferredTokenId !== undefined && !preferred) {
|
|
125
134
|
throw new Error(`Preferred anthropic token ${preferredTokenId} is not available`);
|
|
126
135
|
}
|
|
127
136
|
|
|
128
137
|
const rows = preferred ? [preferred] : [...this.tokenPool.values()];
|
|
138
|
+
|
|
129
139
|
if (rows.length === 0) return null;
|
|
130
140
|
const { eligible, overThresholdTokens } = await this.filterEligibleTokens(rows, model);
|
|
141
|
+
|
|
131
142
|
if (eligible.length === 0) {
|
|
132
143
|
logger.warn("quota_threshold gate: all_exceeded", {
|
|
133
144
|
provider: "anthropic",
|
|
@@ -136,9 +147,11 @@ export class AnthropicDispatcher implements ProviderDispatcher {
|
|
|
136
147
|
overThresholdTokens,
|
|
137
148
|
reason: "all_exceeded",
|
|
138
149
|
});
|
|
150
|
+
|
|
139
151
|
const details = overThresholdTokens
|
|
140
152
|
.map((token) => `${token.tokenName} (threshold ${token.threshold}%)`)
|
|
141
153
|
.join(", ");
|
|
154
|
+
|
|
142
155
|
throw new QuotaThresholdExceededError(
|
|
143
156
|
details
|
|
144
157
|
? `All anthropic tokens exceeded quota threshold: ${details}`
|
|
@@ -149,7 +162,9 @@ export class AnthropicDispatcher implements ProviderDispatcher {
|
|
|
149
162
|
if (preferred) return preferred;
|
|
150
163
|
|
|
151
164
|
const selectedId = this.weightedSelector.select(new Set(eligible.map((token) => token.id)));
|
|
165
|
+
|
|
152
166
|
if (selectedId === null) return null;
|
|
167
|
+
|
|
153
168
|
return this.tokenPool.get(selectedId) ?? null;
|
|
154
169
|
}
|
|
155
170
|
|
|
@@ -161,12 +176,15 @@ export class AnthropicDispatcher implements ProviderDispatcher {
|
|
|
161
176
|
overThresholdTokens: Array<{ tokenName: string; threshold: number }>;
|
|
162
177
|
}> {
|
|
163
178
|
const thresholded = rows.filter((token) => this.hasQuotaThreshold(token));
|
|
179
|
+
|
|
164
180
|
if (thresholded.length === 0) return { eligible: rows, overThresholdTokens: [] };
|
|
165
181
|
|
|
166
182
|
const eligibleIds = new Set(
|
|
167
|
-
rows.
|
|
183
|
+
rows.flatMap((token) => (this.hasQuotaThreshold(token) ? [] : [token.id])),
|
|
168
184
|
);
|
|
185
|
+
|
|
169
186
|
const overThresholdTokens: Array<{ tokenName: string; threshold: number }> = [];
|
|
187
|
+
|
|
170
188
|
const checks = await Promise.allSettled(
|
|
171
189
|
thresholded.map(async (token) => ({
|
|
172
190
|
token,
|
|
@@ -176,11 +194,14 @@ export class AnthropicDispatcher implements ProviderDispatcher {
|
|
|
176
194
|
|
|
177
195
|
checks.forEach((check, index) => {
|
|
178
196
|
const token = check.status === "rejected" ? thresholded[index] : check.value.token;
|
|
197
|
+
|
|
179
198
|
if (!token) return;
|
|
199
|
+
|
|
180
200
|
const result =
|
|
181
201
|
check.status === "fulfilled"
|
|
182
202
|
? check.value.result
|
|
183
203
|
: { kind: "lookup_failed" as const, reason: String(check.reason) };
|
|
204
|
+
|
|
184
205
|
if (result.kind === "lookup_failed") {
|
|
185
206
|
logger.warn("quota_threshold gate: lookup_fail_open", {
|
|
186
207
|
tokenId: token.id,
|
|
@@ -191,6 +212,7 @@ export class AnthropicDispatcher implements ProviderDispatcher {
|
|
|
191
212
|
lookupReason: result.reason,
|
|
192
213
|
});
|
|
193
214
|
eligibleIds.add(token.id);
|
|
215
|
+
|
|
194
216
|
return;
|
|
195
217
|
}
|
|
196
218
|
|
|
@@ -205,6 +227,7 @@ export class AnthropicDispatcher implements ProviderDispatcher {
|
|
|
205
227
|
reason: "over_threshold",
|
|
206
228
|
});
|
|
207
229
|
overThresholdTokens.push({ tokenName: token.name, threshold: token.quotaThreshold });
|
|
230
|
+
|
|
208
231
|
return;
|
|
209
232
|
}
|
|
210
233
|
|
|
@@ -228,7 +251,7 @@ export class AnthropicDispatcher implements ProviderDispatcher {
|
|
|
228
251
|
cb.onThreadId?.(result.threadCoord.threadId);
|
|
229
252
|
cb.onComplete(result);
|
|
230
253
|
} catch (e) {
|
|
231
|
-
cb.onError(e
|
|
254
|
+
cb.onError(e instanceof Error ? e : new Error(String(e)));
|
|
232
255
|
}
|
|
233
256
|
}
|
|
234
257
|
|
|
@@ -238,10 +261,12 @@ export class AnthropicDispatcher implements ProviderDispatcher {
|
|
|
238
261
|
opts?: { includePartialMessages?: boolean },
|
|
239
262
|
): Promise<GenerateResult> {
|
|
240
263
|
this.inFlight++;
|
|
264
|
+
|
|
241
265
|
try {
|
|
242
266
|
if (req.imageGeneration) {
|
|
243
267
|
throw new Error("image generation is not supported on the Anthropic route");
|
|
244
268
|
}
|
|
269
|
+
|
|
245
270
|
assertSupportedOneMillionSuffix(req.model);
|
|
246
271
|
const model = canonicalAnthropicModel(req.model);
|
|
247
272
|
const thinking = resolveAnthropicThinking(model, req.thinking, req.effort);
|
|
@@ -249,11 +274,13 @@ export class AnthropicDispatcher implements ProviderDispatcher {
|
|
|
249
274
|
const jsonSchema = serializeAndValidateDispatchSchema(req.outputSchema, "anthropic");
|
|
250
275
|
|
|
251
276
|
const token = await this.selectToken(model, req.preferredTokenId);
|
|
277
|
+
|
|
252
278
|
if (!token) throw new Error("No anthropic tokens available");
|
|
253
279
|
|
|
254
280
|
// 만료 직전에 갱신하되 실패하면 기존 토큰으로 진행한다.
|
|
255
281
|
let accessToken = token.credentials.accessToken;
|
|
256
282
|
const expiresAt = getExpiresAt(token.credentials);
|
|
283
|
+
|
|
257
284
|
if (
|
|
258
285
|
expiresAt &&
|
|
259
286
|
expiresAt - Date.now() < REFRESH_SAFETY_MS &&
|
|
@@ -267,13 +294,16 @@ export class AnthropicDispatcher implements ProviderDispatcher {
|
|
|
267
294
|
provider: "anthropic",
|
|
268
295
|
name: token.name,
|
|
269
296
|
credentials: token.credentials,
|
|
270
|
-
}
|
|
297
|
+
});
|
|
271
298
|
} catch (e) {
|
|
272
|
-
logger.warn(
|
|
299
|
+
logger.warn(
|
|
300
|
+
`refresh failed for ${token.name}: ${e instanceof Error ? e.message : String(e)}`,
|
|
301
|
+
);
|
|
273
302
|
}
|
|
274
303
|
}
|
|
275
304
|
|
|
276
305
|
logger.info(`→ ${token.name} (model: ${model})`);
|
|
306
|
+
|
|
277
307
|
const session = await runClaudeSession(
|
|
278
308
|
{
|
|
279
309
|
tokenId: token.id,
|
|
@@ -294,20 +324,25 @@ export class AnthropicDispatcher implements ProviderDispatcher {
|
|
|
294
324
|
|
|
295
325
|
if (session.quotaExhausted) {
|
|
296
326
|
invalidateAnthropicQuotaUsage(token.credentials.accessToken);
|
|
327
|
+
|
|
297
328
|
if (accessToken !== token.credentials.accessToken) {
|
|
298
329
|
invalidateAnthropicQuotaUsage(accessToken);
|
|
299
330
|
}
|
|
331
|
+
|
|
300
332
|
throw new Error(`quota exhausted (${token.name})`);
|
|
301
333
|
}
|
|
334
|
+
|
|
302
335
|
if (session.isError) {
|
|
303
336
|
// 종료 사유를 먼저 표시하고 응답 본문은 진단에 필요한 만큼만 남긴다.
|
|
304
337
|
const reason =
|
|
305
338
|
session.subtype ?? session.terminalReason ?? (session.isError ? "is_error" : "unknown");
|
|
339
|
+
|
|
306
340
|
const body = session.text
|
|
307
341
|
? session.text.length > 500
|
|
308
342
|
? `${session.text.slice(0, 500)}…(${session.text.length} chars)`
|
|
309
343
|
: session.text
|
|
310
344
|
: `empty text, outputTokens=${session.usage.outputTokens}`;
|
|
345
|
+
|
|
311
346
|
const refusal = session.refusal ? ` refusal=${JSON.stringify(session.refusal)}` : "";
|
|
312
347
|
throw new Error(`claude error (${token.name}) [${reason}]: ${body}${refusal}`);
|
|
313
348
|
}
|
|
@@ -16,19 +16,23 @@ export async function readAnthropicQuotaUsage(
|
|
|
16
16
|
): Promise<AnthropicQuotaUsageResult> {
|
|
17
17
|
try {
|
|
18
18
|
const { data, cachedAt } = await fetchUsageWithMeta(accessToken);
|
|
19
|
+
|
|
19
20
|
if (data.error) return { kind: "lookup_failed", reason: data.error };
|
|
20
21
|
|
|
21
22
|
const utilizations = [data.five_hour?.utilization];
|
|
23
|
+
|
|
22
24
|
// Fable 계열(5, 5.1)은 5시간 창과 별개로 usage credits 기반 7일 버킷도 소진될 수 있다.
|
|
23
25
|
if (isFableFamilyModel(model)) {
|
|
24
26
|
utilizations.push(data.seven_day_overage_included?.utilization);
|
|
25
27
|
}
|
|
28
|
+
|
|
26
29
|
const utilization = Math.max(
|
|
27
30
|
...utilizations.filter(
|
|
28
|
-
(value): value is number =>
|
|
31
|
+
(value): value is number => value !== null && value !== undefined && Number.isFinite(value),
|
|
29
32
|
),
|
|
30
33
|
);
|
|
31
|
-
|
|
34
|
+
|
|
35
|
+
if (!Number.isFinite(utilization)) {
|
|
32
36
|
return { kind: "lookup_failed", reason: "five_hour utilization unavailable" };
|
|
33
37
|
}
|
|
34
38
|
|
|
@@ -38,6 +42,6 @@ export async function readAnthropicQuotaUsage(
|
|
|
38
42
|
cacheAgeMs: Math.max(Date.now() - cachedAt, 0),
|
|
39
43
|
};
|
|
40
44
|
} catch (e) {
|
|
41
|
-
return { kind: "lookup_failed", reason:
|
|
45
|
+
return { kind: "lookup_failed", reason: e instanceof Error ? e.message : String(e) };
|
|
42
46
|
}
|
|
43
47
|
}
|
|
@@ -27,6 +27,7 @@ let extraBodyRuntimeSupported: boolean | undefined;
|
|
|
27
27
|
/** These modes were verified through native extra-body delivery on Claude Code 2.1.295. */
|
|
28
28
|
export function assertAnthropicThinkingRuntime(extraBody: string | undefined): void {
|
|
29
29
|
if (!extraBody) return;
|
|
30
|
+
|
|
30
31
|
if (extraBodyRuntimeSupported === undefined) {
|
|
31
32
|
try {
|
|
32
33
|
const version = execFileSync("claude", ["--version"], {
|
|
@@ -35,6 +36,7 @@ export function assertAnthropicThinkingRuntime(extraBody: string | undefined): v
|
|
|
35
36
|
stdio: ["ignore", "pipe", "pipe"],
|
|
36
37
|
env: { PATH: process.env.PATH, TMPDIR: process.env.TMPDIR },
|
|
37
38
|
}).match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
39
|
+
|
|
38
40
|
const [major, minor, patch] = version?.slice(1).map(Number) ?? [];
|
|
39
41
|
extraBodyRuntimeSupported =
|
|
40
42
|
major !== undefined &&
|
|
@@ -45,6 +47,7 @@ export function assertAnthropicThinkingRuntime(extraBody: string | undefined): v
|
|
|
45
47
|
extraBodyRuntimeSupported = false;
|
|
46
48
|
}
|
|
47
49
|
}
|
|
50
|
+
|
|
48
51
|
if (!extraBodyRuntimeSupported) {
|
|
49
52
|
throw new ThinkingValidationError(
|
|
50
53
|
"thinking:false for Haiku 5.5 and Sonnet 5.5 requires Claude Code 2.1.295 or later; runtime version could not be verified",
|
|
@@ -54,14 +57,17 @@ export function assertAnthropicThinkingRuntime(extraBody: string | undefined): v
|
|
|
54
57
|
|
|
55
58
|
export function resolveAnthropicThinking(model: string, thinking?: boolean, effort?: string) {
|
|
56
59
|
const canonical = canonicalAnthropicModel(model);
|
|
60
|
+
|
|
57
61
|
if (thinking === false && !THINKING_OFF_MODELS.has(canonical)) {
|
|
58
62
|
const reason = usesAdaptiveThinking(canonical)
|
|
59
63
|
? "this model requires thinking"
|
|
60
64
|
: "thinking-off support has not been verified for this model";
|
|
65
|
+
|
|
61
66
|
throw new ThinkingValidationError(
|
|
62
67
|
`thinking:false is not supported for anthropic/${canonical}: ${reason}`,
|
|
63
68
|
);
|
|
64
69
|
}
|
|
70
|
+
|
|
65
71
|
return {
|
|
66
72
|
// Never accept caller-provided extra body data or inherit it from the host environment.
|
|
67
73
|
extraBody:
|
|
@@ -52,13 +52,16 @@ export async function withSessionLock<T>(sessionId: string, fn: () => Promise<T>
|
|
|
52
52
|
const prev = sessionChains.get(sessionId) ?? Promise.resolve();
|
|
53
53
|
// 이전 turn 의 성패와 무관하게 직렬 체인을 잇는다.
|
|
54
54
|
const next = prev.then(fn, fn);
|
|
55
|
+
|
|
55
56
|
// tail: 성패 무관 settle 되는 핸들. 이걸 맵에 두고, finally 에서 "여전히 내가 끝"일 때만 삭제.
|
|
56
57
|
// (set 직후 undefined 검사로 하면 절대 삭제 안 돼 세션 id 가 누수됨 — tail 일치 검사로 회피.)
|
|
57
58
|
const tail = next.then(
|
|
58
59
|
() => {},
|
|
59
60
|
() => {},
|
|
60
61
|
);
|
|
62
|
+
|
|
61
63
|
sessionChains.set(sessionId, tail);
|
|
64
|
+
|
|
62
65
|
try {
|
|
63
66
|
return await next;
|
|
64
67
|
} finally {
|
|
@@ -127,10 +130,12 @@ export function ensureConfigDir(tokenId: number): string {
|
|
|
127
130
|
mkdirSync(dir, { recursive: true });
|
|
128
131
|
writeFileSync(`${dir}/.claude.json`, "{}");
|
|
129
132
|
writeFileSync(`${dir}/settings.json`, "{}");
|
|
133
|
+
|
|
130
134
|
return dir;
|
|
131
135
|
}
|
|
132
136
|
|
|
133
137
|
let cwdEnsured = false;
|
|
138
|
+
|
|
134
139
|
function ensureCwd(): void {
|
|
135
140
|
if (cwdEnsured) return;
|
|
136
141
|
mkdirSync(`${ANTHROPIC_CLAUDE_CWD}/.claude`, { recursive: true });
|
|
@@ -141,6 +146,7 @@ function ensureCwd(): void {
|
|
|
141
146
|
// spawn args 구성. 멀티턴/격리/structured 모드 반영.
|
|
142
147
|
export function applyOneMillionSuffix(model: string, needsSuffix: boolean): string {
|
|
143
148
|
const base = canonicalAnthropicModel(model);
|
|
149
|
+
|
|
144
150
|
return needsSuffix ? `${base}[1m]` : base;
|
|
145
151
|
}
|
|
146
152
|
|
|
@@ -152,12 +158,18 @@ export function oneMillionEnv(supported: boolean): { CLAUDE_CODE_DISABLE_1M_CONT
|
|
|
152
158
|
// `{rejected}{accepted}` 누적이 AI-SDK 의 JSON.parse 를 깨뜨리므로, retry 자체를 막아 그 경로를
|
|
153
159
|
// 원천 차단한다. `0` 은 CC query loop(`callsThisQuery >= maxRetries`)가 첫 attempt emit 전에
|
|
154
160
|
// 실패시키므로(`error_max_structured_output_retries`) 외부 값이 1 미만이어도 1 로 클램프한다.
|
|
155
|
-
export
|
|
161
|
+
export interface StructuredOutputRetriesEnv {
|
|
156
162
|
MAX_STRUCTURED_OUTPUT_RETRIES: string;
|
|
157
|
-
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function structuredOutputRetriesEnv(
|
|
166
|
+
raw = process.env.MAX_STRUCTURED_OUTPUT_RETRIES,
|
|
167
|
+
): StructuredOutputRetriesEnv {
|
|
158
168
|
if (!raw) return { MAX_STRUCTURED_OUTPUT_RETRIES: "1" };
|
|
159
169
|
const parsed = Number.parseInt(raw, 10);
|
|
170
|
+
|
|
160
171
|
if (!Number.isFinite(parsed)) return { MAX_STRUCTURED_OUTPUT_RETRIES: "1" };
|
|
172
|
+
|
|
161
173
|
return { MAX_STRUCTURED_OUTPUT_RETRIES: String(Math.max(parsed, 1)) };
|
|
162
174
|
}
|
|
163
175
|
|
|
@@ -201,7 +213,9 @@ export function buildClaudeArgs(opts: {
|
|
|
201
213
|
}): Array<string> {
|
|
202
214
|
const thinking = resolveAnthropicThinking(opts.model, opts.thinking, opts.effort);
|
|
203
215
|
const useStructured = Boolean(opts.jsonSchema && opts.jsonSchema.length > 0);
|
|
216
|
+
|
|
204
217
|
if (useStructured) assertAnthropicSchemaArgvSize(opts.jsonSchema!);
|
|
218
|
+
|
|
205
219
|
// --tools "" 로 전체 차단, structured(jsonSchema 있음) 면 StructuredOutput 만 허용.
|
|
206
220
|
const toolArgs = useStructured
|
|
207
221
|
? ["--tools", "", "--allowed-tools", "StructuredOutput"]
|
|
@@ -241,7 +255,9 @@ export function buildClaudeArgs(opts: {
|
|
|
241
255
|
"--session-id",
|
|
242
256
|
opts.sessionId,
|
|
243
257
|
];
|
|
258
|
+
|
|
244
259
|
if (useStructured) args.push("--json-schema", opts.jsonSchema!);
|
|
260
|
+
|
|
245
261
|
return args;
|
|
246
262
|
}
|
|
247
263
|
|
|
@@ -274,6 +290,7 @@ export function runClaudeSession(
|
|
|
274
290
|
// 실제 파일 쓰기는 abort 체크 이후(Promise 안)로 미뤄, 이미 취소된 요청엔 쓰지 않는다.
|
|
275
291
|
const system = req.system ?? "";
|
|
276
292
|
const useSystemPromptFile = Buffer.byteLength(system, "utf8") > SYSTEM_PROMPT_ARGV_MAX_BYTES;
|
|
293
|
+
|
|
277
294
|
const systemPromptFile = useSystemPromptFile
|
|
278
295
|
? `${configDir}/system-prompt-${sessionId}.txt`
|
|
279
296
|
: undefined;
|
|
@@ -294,44 +311,53 @@ export function runClaudeSession(
|
|
|
294
311
|
coldHistory: req.coldHistory,
|
|
295
312
|
input: req.input,
|
|
296
313
|
});
|
|
314
|
+
|
|
297
315
|
const stdinPayload = decorateAndSerialize(inputLines, sessionId);
|
|
298
316
|
|
|
299
317
|
return new Promise<ClaudeSessionResult>((resolve, reject) => {
|
|
300
318
|
if (req.abortSignal?.aborted) {
|
|
301
319
|
reject(new Error("aborted"));
|
|
320
|
+
|
|
302
321
|
return;
|
|
303
322
|
}
|
|
304
323
|
|
|
305
324
|
// 대형 시스템 프롬프트는 spawn 직전에 파일로 기록(argv E2BIG 회피). 종료 시 정리한다.
|
|
306
325
|
if (systemPromptFile) writeFileSync(systemPromptFile, system);
|
|
307
326
|
|
|
327
|
+
const env: NodeJS.ProcessEnv = {
|
|
328
|
+
PATH: process.env.PATH,
|
|
329
|
+
TMPDIR: process.env.TMPDIR,
|
|
330
|
+
CLAUDE_CODE_OAUTH_TOKEN: req.token,
|
|
331
|
+
CLAUDE_CONFIG_DIR: configDir,
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
if (thinking.extraBody) env.CLAUDE_CODE_EXTRA_BODY = thinking.extraBody;
|
|
335
|
+
|
|
336
|
+
env.CLAUDE_CODE_DISABLE_AUTO_MEMORY = "1";
|
|
337
|
+
Object.assign(env, oneMillionEnv(supportsOneMillion));
|
|
338
|
+
env.CLAUDE_CODE_DISABLE_CLAUDE_MDS = "1";
|
|
339
|
+
env.CLAUDE_CODE_DISABLE_TERMINAL_TITLE = "1";
|
|
340
|
+
env.CLAUDE_CODE_DISABLE_BUNDLED_SKILLS = "1";
|
|
341
|
+
env.CLAUDE_CODE_DISABLE_WORKFLOWS = "1";
|
|
342
|
+
env.CLAUDE_CODE_ATTRIBUTION_HEADER = "0";
|
|
343
|
+
|
|
344
|
+
// structured + 스트리밍일 때만 retry 를 고정한다(SON-495). text 모드와 논스트림
|
|
345
|
+
// generate 는 CC 기본 retry 를 그대로 쓴다.
|
|
346
|
+
if (
|
|
347
|
+
shouldPinStructuredRetries({
|
|
348
|
+
useStructured,
|
|
349
|
+
includePartialMessages: req.includePartialMessages,
|
|
350
|
+
})
|
|
351
|
+
) {
|
|
352
|
+
Object.assign(env, structuredOutputRetriesEnv());
|
|
353
|
+
}
|
|
354
|
+
|
|
308
355
|
const child = spawn("claude", args, {
|
|
309
356
|
// stderr 도 캡처: invalid OAuth / 잘못된 플래그 / CLI 검증 실패가
|
|
310
357
|
// "closed without result" 로 뭉개지지 않게 close/error 에 stderr 를 실어 보낸다.
|
|
311
358
|
stdio: ["pipe", "pipe", "pipe"],
|
|
312
359
|
cwd: ANTHROPIC_CLAUDE_CWD,
|
|
313
|
-
env
|
|
314
|
-
PATH: process.env.PATH,
|
|
315
|
-
TMPDIR: process.env.TMPDIR,
|
|
316
|
-
CLAUDE_CODE_OAUTH_TOKEN: req.token,
|
|
317
|
-
CLAUDE_CONFIG_DIR: configDir,
|
|
318
|
-
...(thinking.extraBody ? { CLAUDE_CODE_EXTRA_BODY: thinking.extraBody } : {}),
|
|
319
|
-
CLAUDE_CODE_DISABLE_AUTO_MEMORY: "1",
|
|
320
|
-
...oneMillionEnv(supportsOneMillion),
|
|
321
|
-
CLAUDE_CODE_DISABLE_CLAUDE_MDS: "1",
|
|
322
|
-
CLAUDE_CODE_DISABLE_TERMINAL_TITLE: "1",
|
|
323
|
-
CLAUDE_CODE_DISABLE_BUNDLED_SKILLS: "1",
|
|
324
|
-
CLAUDE_CODE_DISABLE_WORKFLOWS: "1",
|
|
325
|
-
CLAUDE_CODE_ATTRIBUTION_HEADER: "0",
|
|
326
|
-
// structured + 스트리밍일 때만 retry 를 고정한다(SON-495). text 모드와 논스트림
|
|
327
|
-
// generate 는 CC 기본 retry 를 그대로 쓴다.
|
|
328
|
-
...(shouldPinStructuredRetries({
|
|
329
|
-
useStructured,
|
|
330
|
-
includePartialMessages: req.includePartialMessages,
|
|
331
|
-
})
|
|
332
|
-
? structuredOutputRetriesEnv()
|
|
333
|
-
: {}),
|
|
334
|
-
},
|
|
360
|
+
env,
|
|
335
361
|
});
|
|
336
362
|
|
|
337
363
|
let settled = false;
|
|
@@ -346,18 +372,22 @@ export function runClaudeSession(
|
|
|
346
372
|
stderrBuf = (stderrBuf + d.toString()).slice(-STDERR_CAP);
|
|
347
373
|
});
|
|
348
374
|
const stderrSuffix = () => (stderrBuf.trim() ? ` — stderr: ${stderrBuf.trim()}` : "");
|
|
375
|
+
|
|
349
376
|
// spawn 시 쓴 임시 시스템 프롬프트 파일 정리(한 번만). 모든 종료 경로에서 호출한다.
|
|
350
377
|
// 누락돼도 다음 ensureConfigDir 가 디렉토리를 재사용할 뿐이지만, sessionId 별 파일이라
|
|
351
378
|
// 쌓이면 디스크가 차므로 settle 시 즉시 지운다.
|
|
352
379
|
const cleanupSpawnFiles = () => {
|
|
353
380
|
if (!systemPromptFile) return;
|
|
381
|
+
|
|
354
382
|
try {
|
|
355
383
|
unlinkSync(systemPromptFile);
|
|
356
384
|
} catch {
|
|
357
385
|
// 이미 없거나 권한 문제면 무시 — 정리는 best-effort.
|
|
358
386
|
}
|
|
359
387
|
};
|
|
388
|
+
|
|
360
389
|
let cleanupAbort: (() => void) | undefined;
|
|
390
|
+
|
|
361
391
|
const timer = setTimeout(() => {
|
|
362
392
|
if (settled) return;
|
|
363
393
|
settled = true;
|
|
@@ -385,6 +415,7 @@ export function runClaudeSession(
|
|
|
385
415
|
child.kill();
|
|
386
416
|
reject(new Error("aborted"));
|
|
387
417
|
};
|
|
418
|
+
|
|
388
419
|
cleanupAbort = () => req.abortSignal?.removeEventListener("abort", onAbort);
|
|
389
420
|
req.abortSignal?.addEventListener("abort", onAbort, { once: true });
|
|
390
421
|
|
|
@@ -393,13 +424,16 @@ export function runClaudeSession(
|
|
|
393
424
|
buffer += d.toString();
|
|
394
425
|
const lines = buffer.split("\n");
|
|
395
426
|
buffer = lines.pop() ?? "";
|
|
427
|
+
|
|
396
428
|
for (const line of lines) {
|
|
397
429
|
const result = handleStreamJsonLine(line, onTrackedDelta, {
|
|
398
430
|
structuredOutput: useStructured,
|
|
399
431
|
state: streamState,
|
|
400
432
|
});
|
|
433
|
+
|
|
401
434
|
if (result) {
|
|
402
435
|
finish(result);
|
|
436
|
+
|
|
403
437
|
return;
|
|
404
438
|
}
|
|
405
439
|
}
|
|
@@ -47,18 +47,22 @@ export function createFenceStripTransform(): FenceStripTransform {
|
|
|
47
47
|
return {
|
|
48
48
|
push(delta: string): string {
|
|
49
49
|
full += delta;
|
|
50
|
+
|
|
50
51
|
if (bodyStart < 0) {
|
|
51
52
|
bodyStart = resolveLeadingOffset(full);
|
|
53
|
+
|
|
52
54
|
if (bodyStart < 0) return "";
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
const body = full.slice(bodyStart);
|
|
56
58
|
const unemitted = body.slice(emitted);
|
|
57
59
|
const safe = unemitted.length - trailingHoldLength(unemitted);
|
|
60
|
+
|
|
58
61
|
if (safe <= 0) return "";
|
|
59
62
|
|
|
60
63
|
const out = unemitted.slice(0, safe);
|
|
61
64
|
emitted += safe;
|
|
65
|
+
|
|
62
66
|
return out;
|
|
63
67
|
},
|
|
64
68
|
|
|
@@ -76,19 +80,25 @@ export function createFenceStripTransform(): FenceStripTransform {
|
|
|
76
80
|
*/
|
|
77
81
|
function resolveLeadingOffset(text: string): number {
|
|
78
82
|
const trimmedStart = text.trimStart();
|
|
83
|
+
|
|
79
84
|
if (trimmedStart === "") return -1; // 아직 공백뿐 — flush 가 정리한다
|
|
80
85
|
const ws = text.length - trimmedStart.length;
|
|
81
86
|
|
|
82
87
|
if (!trimmedStart.startsWith("`")) return ws;
|
|
88
|
+
|
|
83
89
|
if (/^`{1,2}$/.test(trimmedStart)) return -1; // "```" 로 자랄 수 있음
|
|
84
90
|
|
|
85
91
|
const fence = /^```(?:json)?/i.exec(trimmedStart);
|
|
92
|
+
|
|
86
93
|
if (!fence) return ws; // "`x", "``x" — 펜스가 아니라 본문
|
|
94
|
+
|
|
87
95
|
if (/^```(?:j|js|jso)$/i.test(trimmedStart)) return -1; // "json" 태그가 자라는 중
|
|
88
96
|
|
|
89
97
|
const afterFence = trimmedStart.slice(fence[0].length);
|
|
90
98
|
const afterFenceBody = afterFence.trimStart();
|
|
99
|
+
|
|
91
100
|
if (afterFenceBody === "") return -1; // 펜스 뒤 공백만 — 본문 첫 글자 대기
|
|
101
|
+
|
|
92
102
|
return ws + fence[0].length + (afterFence.length - afterFenceBody.length);
|
|
93
103
|
}
|
|
94
104
|
|
|
@@ -101,5 +111,6 @@ function resolveLeadingOffset(text: string): number {
|
|
|
101
111
|
*/
|
|
102
112
|
function trailingHoldLength(unemitted: string): number {
|
|
103
113
|
const match = /(?:\n?`{1,3})?[\s]*$/.exec(unemitted);
|
|
114
|
+
|
|
104
115
|
return match ? match[0].length : 0;
|
|
105
116
|
}
|