@cartanova/qgrid-cli 2.9.10 → 2.10.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.
Files changed (74) hide show
  1. package/bundle/dist/application/qgrid/conv-routing.js +4 -14
  2. package/bundle/dist/application/qgrid/qgrid.dispatcher.js +10 -5
  3. package/bundle/dist/application/qgrid/qgrid.frame.js +7 -2
  4. package/bundle/dist/application/qgrid/qgrid.types.js +3 -1
  5. package/bundle/dist/application/request-log/request-log.model.js +14 -12
  6. package/bundle/dist/application/request-log-step/request-log-step.model.js +7 -11
  7. package/bundle/dist/application/setting/setting.model.js +13 -27
  8. package/bundle/dist/application/token/token.model.js +52 -47
  9. package/bundle/dist/server-error-handler.js +1 -1
  10. package/bundle/dist/sonamu.config.js +3 -15
  11. package/bundle/dist/utils/providers/anthropic/anthropic-constants.js +4 -2
  12. package/bundle/dist/utils/providers/common/model-cost.js +10 -3
  13. package/bundle/src/application/qgrid/conv-routing.test.ts +0 -32
  14. package/bundle/src/application/qgrid/conv-routing.ts +7 -26
  15. package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +65 -121
  16. package/bundle/src/application/qgrid/qgrid.dispatcher.ts +12 -6
  17. package/bundle/src/application/qgrid/qgrid.frame.test.ts +13 -26
  18. package/bundle/src/application/qgrid/qgrid.frame.ts +9 -3
  19. package/bundle/src/application/qgrid/qgrid.types.ts +2 -0
  20. package/bundle/src/application/request-log/request-log.model.test.ts +37 -2
  21. package/bundle/src/application/request-log/request-log.model.ts +14 -7
  22. package/bundle/src/application/request-log-step/request-log-step.model.ts +3 -15
  23. package/bundle/src/application/setting/setting.constant.test.ts +1 -13
  24. package/bundle/src/application/setting/setting.model.ts +10 -26
  25. package/bundle/src/application/setting/setting.persistence.test.ts +27 -0
  26. package/bundle/src/application/token/token.model.test.ts +86 -19
  27. package/bundle/src/application/token/token.model.ts +59 -44
  28. package/bundle/src/server-error-handler.ts +1 -2
  29. package/bundle/src/sonamu.config.ts +4 -31
  30. package/bundle/src/utils/providers/anthropic/anthropic-constants.test.ts +6 -1
  31. package/bundle/src/utils/providers/anthropic/anthropic-constants.ts +5 -2
  32. package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.test.ts +1 -26
  33. package/bundle/src/utils/providers/common/model-cost.test.ts +22 -1
  34. package/bundle/src/utils/providers/common/model-cost.ts +22 -5
  35. package/bundle/src/utils/providers/common/provider-dispatcher.ts +4 -11
  36. package/bundle/web-dist/client/assets/index-Cq4_ExLO.js +106 -0
  37. package/bundle/web-dist/client/assets/logs-kg1KOMBk.js +1 -0
  38. package/bundle/web-dist/client/assets/{monit-C6ZRFTQr.js → monit-DmtHTmSM.js} +1 -1
  39. package/bundle/web-dist/client/assets/{routes-CrMRMQvC.js → routes-CXotE1OF.js} +1 -1
  40. package/bundle/web-dist/client/assets/services.generated-Cbvg2sGQ.js +51 -0
  41. package/bundle/web-dist/client/assets/{settings-BVhU4Oul.js → settings-CfJDz4AC.js} +1 -1
  42. package/bundle/web-dist/client/assets/show-gBpWK4z2.js +2 -0
  43. package/bundle/web-dist/client/assets/{tokens-DliSEDiF.js → tokens-CbFJjIyC.js} +1 -1
  44. package/bundle/web-dist/client/assets/use-oauth-login-flow-jJo7GV3r.js +1 -0
  45. package/bundle/web-dist/client/assets/{use-update-token-mutation-Dkv_HG-C.js → use-update-token-mutation-D-Y8OySK.js} +1 -1
  46. package/bundle/web-dist/client/index.html +2 -2
  47. package/bundle/web-dist/server/assets/{lazyRouteComponent-DyizoQKi.js → lazyRouteComponent-Bj1cPq6x.js} +2 -2
  48. package/bundle/web-dist/server/assets/{logs-DO8zBdBR.js → logs-DMlOXcDS.js} +20 -12
  49. package/bundle/web-dist/server/assets/{monit-COH4MckI.js → monit-Dg1wZCdx.js} +3 -3
  50. package/bundle/web-dist/server/assets/{plus-C1D8z9o0.js → plus-DVobMrag.js} +1 -1
  51. package/bundle/web-dist/server/assets/{react-dom-PfWvArTX.js → react-dom-BjR1Iaz8.js} +1 -1
  52. package/bundle/web-dist/server/assets/{routes-Btja-741.js → routes-C7lB2Q85.js} +5 -5
  53. package/bundle/web-dist/server/assets/{services.generated-BsKOUSXl.js → services.generated-BM4X3Ecj.js} +102 -6
  54. package/bundle/web-dist/server/assets/{settings-DPcWGvy-.js → settings-BaIBt_Vs.js} +4 -4
  55. package/bundle/web-dist/server/assets/{show-CMXbb3TJ.js → show-CDxGr4rS.js} +9 -8
  56. package/bundle/web-dist/server/assets/{tokens-DAUmTrgO.js → tokens-DJlfeGcx.js} +5 -5
  57. package/bundle/web-dist/server/assets/{use-oauth-login-flow-GsGwqefs.js → use-oauth-login-flow-DYKnG4A2.js} +32 -15
  58. package/bundle/web-dist/server/assets/{use-update-token-mutation-RujWERvj.js → use-update-token-mutation-DqGMopII.js} +1 -1
  59. package/bundle/web-dist/server/entry-server.generated.js +381 -21
  60. package/package.json +1 -1
  61. package/skills/qgrid/SKILL.md +6 -0
  62. package/skills/qgrid/references/ai-sdk-provider-contract.md +8 -2
  63. package/skills/qgrid/references/anthropic-claude-code-runtime.md +3 -2
  64. package/skills/qgrid/references/request-log-run-lifecycle.md +4 -0
  65. package/skills/qgrid/references/sonamu-api-web-flow.md +1 -1
  66. package/skills/qgrid/references/token-auth-quota-lifecycle.md +2 -0
  67. package/skills/qgrid/references/verification-and-debugging.md +24 -13
  68. package/bundle/dist/utils/providers/common/token-picker.js +0 -14
  69. package/bundle/src/utils/providers/common/token-picker.ts +0 -18
  70. package/bundle/web-dist/client/assets/index-DJpa8UaG.js +0 -106
  71. package/bundle/web-dist/client/assets/logs-COwHodGU.js +0 -1
  72. package/bundle/web-dist/client/assets/services.generated-Bg2XkD-D.js +0 -51
  73. package/bundle/web-dist/client/assets/show-DA-1k3Mt.js +0 -2
  74. package/bundle/web-dist/client/assets/use-oauth-login-flow-C0qa-nOp.js +0 -1
@@ -68,7 +68,7 @@ Do not write `providerOptions: { ... } satisfies QgridProviderOptions`: the expo
68
68
  - `reasoningSummary`: OpenAI/Codex route only.
69
69
  - `serviceTier`: OpenAI/Codex route only.
70
70
  - `timeoutMs`: Anthropic server-side Claude Code process timeout in milliseconds. It must be a positive integer no greater than 30 minutes and defaults to 240 seconds. For non-stream `generateText`, the SDK derives request-scoped Undici `headersTimeout` and `bodyTimeout` values as `timeoutMs + 60_000` without changing the process-global dispatcher.
71
- - `fallbackModels`: reserved for future qgrid server-side fallback routing. It is not the Fable 5 safety-refusal fallback, which is owned by Claude Code upstream.
71
+ - `fallbackModels`: deprecated, ignored compatibility field. The provider emits a standard unsupported-option warning when supplied; remove it from callers. It is not Claude Code's upstream Fable safety-refusal fallback.
72
72
  - `imageGeneration`: OpenAI/Codex non-stream only. Enables Codex's built-in `image_generation` tool for that request.
73
73
  - `imageGenerationOptions`: optional `quality: "low" | "medium" | "high"`, `size: "1024x1024" | "1024x1536" | "1536x1024"`, and `background: "auto" | "opaque" | "transparent"`. Transparent requests use Codex standalone Images with `gpt-image-2`; other requests use the hosted Responses tool. Transparent mode rejects tools/structured output, supports up to five references, validates real transparent and visible PNG pixels, and never invokes background-removal fallback. Returned size/quality may differ from requested settings; read `result.providerMetadata.qgrid.imageGeneration` or per-file `result.content` metadata. `result.files[]` contains bytes/mediaType only. Logs separate `requestedOptions` from `observedGeneration`; image usage is separate from the zero text-driver usage on this route.
74
74
 
@@ -199,6 +199,12 @@ Reference images for image generation use normal AI SDK multimodal message parts
199
199
 
200
200
  ## Response mapping
201
201
 
202
+ Cancelling the returned provider stream aborts its HTTP request and releases the SSE reader; caller abort signals propagate through the same request-local cancellation path. Normal completion and error events also release the reader. OpenAI affinity coordinates are swept for expiration on insertion and bounded to the most recently issued 1,000 entries; eviction keeps full-history generation functional.
203
+
204
+ Since 2.10.0, `generateText` exposes the parent request-log ID at `result.providerMetadata?.qgrid?.requestLogId`. For `streamText`, consume the stream first, then read `(await result.providerMetadata)?.qgrid?.requestLogId`. The raw query response and stream `done` event carry optional top-level `requestLogId`.
205
+
206
+ Update both server and SDK to use this metadata. The field is omitted when logging is disabled or an older server does not return it. Tool-run steps share the parent ID; `runContext.requestLogId` remains separate continuation state. This does not expose external-provider telemetry logger IDs or add IDs to stream delta/error events.
207
+
202
208
  qgrid response content maps to AI SDK content:
203
209
 
204
210
  - qgrid `text` -> AI SDK text content.
@@ -222,7 +228,7 @@ For a successful Fable refusal fallback (Fable 5 or 5.1):
222
228
  - `providerMetadata.qgrid.modelFallbacks` preserves the refusal route and optional category/explanation.
223
229
  - `providerMetadata.qgrid.costSource` reports whether cost came from Claude Code or qgrid's pricing table. Prefer the provider-reported combined cost for this path.
224
230
 
225
- Do not expose the requested Fable model as `response.modelId` after Opus served the answer, and do not map this upstream safety behavior onto the reserved `providerOptions.qgrid.fallbackModels` option.
231
+ Do not expose the requested Fable model as `response.modelId` after Opus served the answer, and do not map this upstream safety behavior onto the deprecated `providerOptions.qgrid.fallbackModels` option.
226
232
 
227
233
  Usage maps qgrid standard usage into AI SDK V3 usage:
228
234
 
@@ -77,7 +77,7 @@ claude -p
77
77
  --model <canonical-model-or-1m-suffix>
78
78
  --system-prompt <text> # small system prompt
79
79
  --system-prompt-file <path> # large system prompt
80
- --thinking disabled # omitted for Fable 5/5.1, Opus 5, Opus 5.5 and Sonnet 5.5
80
+ --thinking disabled # omitted for Fable 5/5.1, Opus 5, Opus 5.5, Sonnet 5.5 and Haiku 5.5
81
81
  --effort <effort-or-low>
82
82
  --disable-slash-commands
83
83
  --session-id <uuid>
@@ -97,7 +97,7 @@ Important details:
97
97
  - Large system prompts over 64 KiB are written to a temporary file to avoid argv `E2BIG` — this
98
98
  same branch absorbs large injected schema contracts, so the old 64 KiB schema argv limit no
99
99
  longer applies (only the global 512 KiB caller-schema complexity limit remains).
100
- - `--thinking disabled`, `MAX_THINKING_TOKENS=0`, and adaptive thinking env suppression keep thinking off for existing models. Fable 5, Fable 5.1, Opus 5.5 and Sonnet 5.5 require always-on adaptive thinking (Fable: CLI catalog `rejects_disabled_thinking`; Opus 5.5: official spec, thinking cannot be turned off; Sonnet 5.5: API `{type: "disabled"}` returns 400 and the CLI catalog marks `rejects_disabled_thinking`). Opus 5 defaults to adaptive thinking and rejects disabled thinking at `xhigh`/`max` effort. qgrid omits all three suppressors for these models (`usesAdaptiveThinking`) and uses `effort` to control depth.
100
+ - `--thinking disabled`, `MAX_THINKING_TOKENS=0`, and adaptive thinking env suppression keep thinking off for existing models. Fable 5, Fable 5.1, Opus 5.5, Sonnet 5.5 and Haiku 5.5 require always-on adaptive thinking (Fable: CLI catalog `rejects_disabled_thinking`; Opus 5.5: official spec, thinking cannot be turned off; Sonnet 5.5: API `{type: "disabled"}` returns 400 and the CLI catalog marks `rejects_disabled_thinking`; Haiku 5.5 (released 2026-10-07): the API accepts disabled thinking only at `high` effort or below and returns 400 at `xhigh`/`max`, and the Claude Code 2.1.293 catalog marks `rejects_disabled_thinking`). Opus 5 defaults to adaptive thinking and rejects disabled thinking at `xhigh`/`max` effort. qgrid omits all three suppressors for these models (`usesAdaptiveThinking`) and uses `effort` to control depth.
101
101
 
102
102
  ## Spawn env
103
103
 
@@ -260,6 +260,7 @@ qgrid's exact 1M support set currently includes:
260
260
  - `claude-opus-5-5`
261
261
  - `claude-sonnet-5-5`
262
262
  - `claude-sonnet-5`
263
+ - `claude-haiku-5-5`
263
264
  - `claude-sonnet-4-6`
264
265
  - `claude-opus-4-6`
265
266
  - `claude-opus-4-8`
@@ -38,6 +38,8 @@ Candidate discovery is only a hint; each candidate is rechecked and finalized in
38
38
 
39
39
  ## Tool-call loop
40
40
 
41
+ Since 2.10.0, the frame returns the parent `requestLogId` at the top level of successful query responses and stream `done` events, including terminal text responses. It retains the allocated ID if logging postprocessing fails after provider success. The field is absent with `logger: false`. Tool-run steps share the ID, while `runContext.requestLogId` remains reserved for continuing pending tool calls. SDK callers read `providerMetadata.qgrid.requestLogId`; streaming metadata becomes available at completion. Delta and error events are unchanged.
42
+
41
43
  The AI SDK provider tracks pending tool-call IDs. When the next AI SDK call contains all required tool results, it sends the existing logging `runContext` when one was returned and sends the tool results. With `logger: false`, it still correlates the pending calls locally and continues the generation without a request-log id.
42
44
 
43
45
  qgrid converts tool results into continuation input for providers. Cold fallback still includes a "continue using these results" text input.
@@ -61,6 +63,8 @@ Provider-qualified ids widen `model_name` and `requested_model_name` from 50 to
61
63
 
62
64
  ## Usage fields
63
65
 
66
+ The dashboard total includes driver `cost_usd` and `image_cost_usd` once each. Both the stored sum and legacy driver-price adjustment apply the same normalized Sonamu filters as the list. The `/api/qgrid/stats` `requests` field is an in-memory count of completed provider generations since process start, separated by provider and token name; tool follow-up generations count separately. It is not a persisted lifetime count or a count of failed attempts.
67
+
64
68
  Stored request log usage uses qgrid-standard semantics:
65
69
 
66
70
  - `input_tokens`: total input, including cache read/write.
@@ -72,7 +72,7 @@ Clicking an attached or generated image opens a preview with extension, decoded
72
72
 
73
73
  Token credential previews must tolerate missing `accessToken` rather than reading `.length` unconditionally. Legacy system-keychain credentials display `System Keychain`; this display compatibility does not enable an Antigravity runtime.
74
74
 
75
- Chat model presets: the model `<select>` lists the served subset of `QgridSupportedModel` grouped by provider (`MODEL_PRESET_GROUPS` in `ChatWidget.tsx`), newest first, and defaults to `anthropic/claude-fable-5-1`. Ids that the ChatGPT-subscription Codex route no longer serves (`gpt-5.4` and `gpt-5.4-mini` retired 2026-08-31 with `gpt-5.6-terra` / `gpt-5.6-luna` as replacements; `gpt-5.2` and `gpt-5.3-codex` removed earlier), `gpt-5.3-codex-spark` (rejected on the ChatGPT-account Codex route and absent from its catalog as of 2026-09-29), `gpt-5.5` (retires from the Codex/ChatGPT route on 2026-10-14; replacements `gpt-6.1-sol` / `gpt-6-luna`), the retired `claude-opus-4` / `claude-sonnet-4` (2026-06-15) and `claude-opus-4-1` (2026-08-05; Claude Code silently serves `claude-opus-5-5` instead), and the catalog-less `claude-sonnet-4-7` stay in the SDK type and price table (legacy request-log cost) but are excluded here. web does not depend on ai-sdk, so a new model must be added in both places. `openai/gpt-6-astra`, `openai/gpt-6.1-sol`, `openai/gpt-6-sol`, and `openai/gpt-6-luna` are included in the OpenAI group and `anthropic/claude-opus-5-5` and `anthropic/claude-sonnet-5-5` in the Anthropic group; adding them does not change the default model.
75
+ Chat model presets: the model `<select>` lists the served subset of `QgridSupportedModel` grouped by provider (`MODEL_PRESET_GROUPS` in `ChatWidget.tsx`), newest first, and defaults to `anthropic/claude-fable-5-1`. Ids that the ChatGPT-subscription Codex route no longer serves (`gpt-5.4` and `gpt-5.4-mini` retired 2026-08-31 with `gpt-5.6-terra` / `gpt-5.6-luna` as replacements; `gpt-5.2` and `gpt-5.3-codex` removed earlier), `gpt-5.3-codex-spark` (rejected on the ChatGPT-account Codex route and absent from its catalog as of 2026-09-29), `gpt-5.5` (retires from the Codex/ChatGPT route on 2026-10-14; replacements `gpt-6.1-sol` / `gpt-6-luna`), the retired `claude-opus-4` / `claude-sonnet-4` (2026-06-15) and `claude-opus-4-1` (2026-08-05; Claude Code silently serves `claude-opus-5-5` instead), and the catalog-less `claude-sonnet-4-7` stay in the SDK type and price table (legacy request-log cost) but are excluded here. web does not depend on ai-sdk, so a new model must be added in both places. `openai/gpt-6-astra`, `openai/gpt-6.1-sol`, `openai/gpt-6-sol`, and `openai/gpt-6-luna` are included in the OpenAI group and `anthropic/claude-opus-5-5`, `anthropic/claude-sonnet-5-5`, and `anthropic/claude-haiku-5-5` in the Anthropic group; adding them does not change the default model.
76
76
 
77
77
  The monit tab's vitals strip shows per-provider in-flight counts, an in-flight sparkline, token chips with quota gauges (fed by the dispatcher's 60-second rate-limits cache; `resetsAt` arrives as ms epoch), and a 1-hour per-provider request/error/cache-hit stats line polled separately every 30 seconds.
78
78
 
@@ -42,6 +42,8 @@ Use this reference before changing token storage, OAuth flows, token activation,
42
42
  On creation, the database defaults `reauth_required = false`; `TokenModel.save` also applies `quota_threshold = 80` and `weight = 1` independently for any field not provided (skipped entirely when `id` is present).
43
43
  `TokenModel.save` is internal only; callers use the curated qgrid token APIs so they cannot write lifecycle fields directly.
44
44
 
45
+ Account re-login reads, deletes, and replaces matching token rows in one explicit Puri transaction. A failed insert rolls back deletion. The oldest matching row supplies quota threshold (including null), weight, and dashboard order unless the caller explicitly supplies them; keepalive stays enabled if any replaced row enabled it. The new login still receives a new ID and resets active/reauth state. Internal full-pool reads use unlimited list mode rather than a 100-row page.
46
+
45
47
  Dashboard credential previews must tolerate legacy credentials without `accessToken`. System-keychain credentials, including a remaining Antigravity row, display `System Keychain` rather than crashing on `.length`. This 2.9.8 display fix neither deletes legacy rows nor enables Antigravity provider execution.
46
48
 
47
49
  OpenAI credentials:
@@ -10,6 +10,12 @@ Use this reference to choose tests, smoke scripts, and first debugging targets f
10
10
  - Common error triage
11
11
  - Debugging rules
12
12
 
13
+ ## Keep Tests Lightweight
14
+
15
+ Cover user-visible flows with a small real-provider E2E suite. Keep focused tests for costs, validation, cancellation, transactions, and actual regressions that a successful live request cannot prove. Remove obsolete behavior and duplicate assertions; do not delete distinct contracts just because their tests use mocks or are long. Call counts matter when they detect duplicate generation or logging, not merely an internal implementation choice.
16
+
17
+ Prefer existing checks and fixtures. Do not add a generic harness, blanket coverage target, snapshot suite, or configuration-only test layer. After the relevant checks pass, repeat only for a new edit, failure, or concrete unresolved risk. Keep production fixes separate from test cleanup and never weaken a test to hide a discovered defect.
18
+
13
19
  ## Package Scripts
14
20
 
15
21
  The commands in this section apply only inside the qgrid source repository. In a downstream
@@ -18,13 +24,17 @@ project, use that project's configured task and tool runner.
18
24
  Root:
19
25
 
20
26
  - `mise run check`: qgrid docs consistency, oxlint, and oxfmt check for the repo.
27
+ - `mise run test`: DB-free API tests, SDK tests, and CLI packaging tests. No provider credentials are needed; the OAuth relay test opens a local loopback listener.
21
28
  - `mise run build`: recursive package build.
22
29
  - `mise run dev`: parallel package dev servers.
23
30
 
24
31
  API package `qgrid-api`:
25
32
 
26
- - `mise exec -- pnpm --filter qgrid-api test`: Vitest run.
27
- - `mise exec -- pnpm --filter qgrid-api test:watch`: standalone watch mode.
33
+ - `mise exec -- pnpm --filter qgrid-api test:unit`: DB-free tests with per-file isolation. Add a test path to select a file.
34
+ - `mise exec -- pnpm --filter qgrid-api test:db`: model/transaction suites requiring a prepared local PostgreSQL test template. Missing DB is a failure, not a skip.
35
+ - `mise exec -- pnpm --filter qgrid-api test`: both suites, unit first.
36
+ - `mise exec -- pnpm --filter qgrid-api test:watch`: DB-free watch mode; use `test:db --watch` for DB tests.
37
+ - `mise exec -- pnpm --filter qgrid-api test:coverage`: both suites, with separate `coverage/unit` and `coverage/db` reports.
28
38
  - `mise exec -- pnpm --filter qgrid-api build`: Sonamu build.
29
39
  - `mise exec -- pnpm --filter qgrid-api sonamu`: run Sonamu CLI.
30
40
 
@@ -83,7 +93,11 @@ Run focused Vitest files from the owning package when possible, then broaden if
83
93
 
84
94
  ## Smoke Scripts
85
95
 
86
- Smoke scripts assume a running qgrid server and real registered tokens. They can consume subscription quota; do not run them casually.
96
+ Real-provider E2E requires a prepared isolated qgrid server, a registered token, and explicit opt-in. It consumes subscription quota; do not run it against production as part of routine checks. Never report mocked tests as live-provider verification.
97
+
98
+ The default entry point is `packages/ai-sdk/e2e/e2e.ts` (`mise exec -- pnpm --dir packages/ai-sdk e2e`). It checks text, streaming, and tool-plus-structured output, and follows each returned `requestLogId` to the persisted parent and steps. Set `QGRID_REAL_PROVIDER_ACCEPTANCE=1`, `QGRID_URL`, and `QGRID_MODEL` explicitly. A comma-separated model list explicitly selects multiple provider runs. Each run uses a unique project label; no production logs are deleted. Exact prose, token counts, costs, and timing are not acceptance criteria.
99
+
100
+ CI runs the DB-free tests plus existing package and empty-DB boot checks. Live E2E remains an explicit command; unavailable credentials or infrastructure mean unverified, not passed.
87
101
 
88
102
  OpenAI direct qgrid API:
89
103
 
@@ -109,16 +123,8 @@ AI SDK structured output:
109
123
  AI SDK tools plus structured output:
110
124
 
111
125
  - `packages/ai-sdk/e2e/tools-structured-output.ts`
112
- - This is the public-path release acceptance matrix: `qgrid()` HTTP/SSE,
113
- `generateText`/`streamText`, OpenAI/Anthropic, direct final answers, and one
114
- client-tool result followed by `Output.object`.
115
- - It consumes real provider quota and requires the explicit
116
- `QGRID_REAL_PROVIDER_ACCEPTANCE=1` opt-in.
117
- - Uses `QGRID_URL`, `QGRID_ACCEPTANCE_OPENAI_MODEL`, and
118
- `QGRID_ACCEPTANCE_ANTHROPIC_MODEL`. OpenAI direct-final coverage defaults to
119
- 10 generate plus 10 stream attempts and can be changed with
120
- `QGRID_ACCEPTANCE_OPENAI_DIRECT_REPEATS_PER_MODE`. Request logs use the stable
121
- project name `qgrid-ai-sdk-tools-output-acceptance`.
126
+ - Focused regression probe for direct structured answers while tools are available, including OpenAI tuple output, streamed JSON, and streaming tool follow-up. The non-streaming tool execution happy path lives in the default E2E suite.
127
+ - Uses the same explicit opt-in, server, and model selection as default E2E. Runs once per mode by default; set `QGRID_ACCEPTANCE_REPEATS` only for an intentional repeated probe.
122
128
 
123
129
  Image generation:
124
130
 
@@ -135,6 +141,11 @@ Other scripts under `scripts/smoke-test-*` and `scripts/debug-*` are ad hoc prob
135
141
 
136
142
  ## Common Error Triage
137
143
 
144
+ Generated SSE handlers missing a newly added event field:
145
+
146
+ - Sonamu's service generator reads runtime stream-decorator schemas. A stale API `dist` can keep the old event shape even with `sonamu sync --force`.
147
+ - Run `mise exec -- pnpm --dir packages/api sonamu build api`, then `mise exec -- pnpm --dir packages/api sonamu sync --force`. Check the generated handler type and web typecheck; do not hand-edit generated services.
148
+
138
149
  `NO_OPENAI_WORKERS`:
139
150
 
140
151
  - The request path returns this only when there is no active OpenAI token candidate; there is no queue and no busy state.
@@ -1,14 +0,0 @@
1
- //#region src/utils/providers/common/token-picker.ts
2
- var RoundRobinPicker = class {
3
- cursor = 0;
4
- pick(tokens) {
5
- if (tokens.length === 0) return null;
6
- const picked = tokens[this.cursor % tokens.length];
7
- this.cursor++;
8
- return picked;
9
- }
10
- };
11
- //#endregion
12
- export { RoundRobinPicker };
13
-
14
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW4tcGlja2VyLmpzIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy91dGlscy9wcm92aWRlcnMvY29tbW9uL3Rva2VuLXBpY2tlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFRva2VuUGlja2VyIOKAlCDthqDtgbAg7ISg7YOdIOyVjOqzoOumrOymmCDsnbjthLDtjpjsnbTsiqQgKyBSb3VuZFJvYmluUGlja2VyIOq1rO2YhC5cbiAqL1xuXG5leHBvcnQgaW50ZXJmYWNlIFRva2VuUGlja2VyPFQgZXh0ZW5kcyB7IGlkOiBudW1iZXIgfT4ge1xuICBwaWNrKHRva2VuczogVFtdKTogVCB8IG51bGw7XG59XG5cbmV4cG9ydCBjbGFzcyBSb3VuZFJvYmluUGlja2VyPFQgZXh0ZW5kcyB7IGlkOiBudW1iZXIgfT4gaW1wbGVtZW50cyBUb2tlblBpY2tlcjxUPiB7XG4gIHByaXZhdGUgY3Vyc29yID0gMDtcblxuICBwaWNrKHRva2VuczogVFtdKTogVCB8IG51bGwge1xuICAgIGlmICh0b2tlbnMubGVuZ3RoID09PSAwKSByZXR1cm4gbnVsbDtcbiAgICBjb25zdCBwaWNrZWQgPSB0b2tlbnNbdGhpcy5jdXJzb3IgJSB0b2tlbnMubGVuZ3RoXSE7XG4gICAgdGhpcy5jdXJzb3IrKztcbiAgICByZXR1cm4gcGlja2VkO1xuICB9XG59XG4iXSwibWFwcGluZ3MiOiI7QUFRQSxJQUFhLG1CQUFiLE1BQWtGO0NBQ2hGLFNBQWlCO0NBRWpCLEtBQUssUUFBdUI7RUFDMUIsSUFBSSxPQUFPLFdBQVcsR0FBRyxPQUFPO0VBQ2hDLE1BQU0sU0FBUyxPQUFPLEtBQUssU0FBUyxPQUFPO0VBQzNDLEtBQUs7RUFDTCxPQUFPO0NBQ1Q7QUFDRiJ9
@@ -1,18 +0,0 @@
1
- /**
2
- * TokenPicker — 토큰 선택 알고리즘 인터페이스 + RoundRobinPicker 구현.
3
- */
4
-
5
- export interface TokenPicker<T extends { id: number }> {
6
- pick(tokens: T[]): T | null;
7
- }
8
-
9
- export class RoundRobinPicker<T extends { id: number }> implements TokenPicker<T> {
10
- private cursor = 0;
11
-
12
- pick(tokens: T[]): T | null {
13
- if (tokens.length === 0) return null;
14
- const picked = tokens[this.cursor % tokens.length]!;
15
- this.cursor++;
16
- return picked;
17
- }
18
- }