@cartanova/qgrid-cli 2.5.3 → 2.5.4

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 (62) hide show
  1. package/README.ko.md +7 -2
  2. package/README.md +7 -2
  3. package/bundle/dist/application/monit/monit.frame.js +3 -3
  4. package/bundle/dist/application/qgrid/oauth.js +1 -1
  5. package/bundle/dist/application/qgrid/qgrid.dispatcher.js +36 -14
  6. package/bundle/dist/application/qgrid/qgrid.frame.js +19 -5
  7. package/bundle/dist/application/qgrid/tool-emulation-schema.js +121 -0
  8. package/bundle/dist/application/qgrid/tool-emulation.js +116 -96
  9. package/bundle/dist/application/request-log/request-log.model.js +3 -3
  10. package/bundle/dist/application/request-log-step/request-log-step.model.js +2 -2
  11. package/bundle/dist/application/token/token.model.js +2 -2
  12. package/bundle/dist/server-error-handler.js +15 -0
  13. package/bundle/dist/sonamu.config.js +4 -7
  14. package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +4 -3
  15. package/bundle/dist/utils/providers/anthropic/claude-session.js +7 -5
  16. package/bundle/dist/utils/providers/common/schema-validation.js +178 -0
  17. package/bundle/dist/utils/providers/common/strictifier.js +329 -42
  18. package/bundle/dist/utils/providers/openai/codex-worker.js +16 -8
  19. package/bundle/dist/utils/providers/openai/openai-dispatcher.js +5 -37
  20. package/bundle/dist/utils/providers/openai/openai-worker-pool-config.js +37 -0
  21. package/bundle/src/application/monit/monit.frame.ts +1 -1
  22. package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +103 -0
  23. package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +337 -0
  24. package/bundle/src/application/qgrid/qgrid.dispatcher.ts +45 -25
  25. package/bundle/src/application/qgrid/qgrid.frame.test.ts +580 -8
  26. package/bundle/src/application/qgrid/qgrid.frame.ts +28 -1
  27. package/bundle/src/application/qgrid/tool-emulation-schema.test.ts +188 -0
  28. package/bundle/src/application/qgrid/tool-emulation-schema.ts +176 -0
  29. package/bundle/src/application/qgrid/tool-emulation.test.ts +285 -67
  30. package/bundle/src/application/qgrid/tool-emulation.ts +199 -102
  31. package/bundle/src/server-error-handler.ts +22 -0
  32. package/bundle/src/sonamu.config.test.ts +37 -0
  33. package/bundle/src/sonamu.config.ts +2 -5
  34. package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.test.ts +44 -0
  35. package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +2 -2
  36. package/bundle/src/utils/providers/anthropic/claude-session.test.ts +10 -0
  37. package/bundle/src/utils/providers/anthropic/claude-session.ts +6 -1
  38. package/bundle/src/utils/providers/common/schema-validation.test.ts +284 -0
  39. package/bundle/src/utils/providers/common/schema-validation.ts +308 -0
  40. package/bundle/src/utils/providers/common/strictifier.test.ts +746 -0
  41. package/bundle/src/utils/providers/common/strictifier.ts +513 -52
  42. package/bundle/src/utils/providers/openai/codex-worker.test.ts +31 -0
  43. package/bundle/src/utils/providers/openai/codex-worker.ts +12 -4
  44. package/bundle/src/utils/providers/openai/openai-dispatcher.test.ts +6 -4
  45. package/bundle/src/utils/providers/openai/openai-dispatcher.ts +6 -79
  46. package/bundle/src/utils/providers/openai/openai-worker-pool-config.ts +80 -0
  47. package/bundle/web-dist/client/assets/{index-DXdGBfB8.js → index-DiY5V2e3.js} +3 -3
  48. package/bundle/web-dist/client/assets/{logs-D_j1yxC4.js → logs-UZ4Cvdmc.js} +1 -1
  49. package/bundle/web-dist/client/assets/{monit-CIToyoxW.js → monit-C5cJo-HD.js} +1 -1
  50. package/bundle/web-dist/client/assets/{routes-Dd21A-wi.js → routes-DEKEmoQN.js} +1 -1
  51. package/bundle/web-dist/client/assets/{show-DfePWRbc.js → show-DnX6b8KG.js} +1 -1
  52. package/bundle/web-dist/client/assets/{tokens-B4MV2fdk.js → tokens-Ct0FGD4b.js} +1 -1
  53. package/bundle/web-dist/client/index.html +1 -1
  54. package/bundle/web-dist/server/entry-server.generated.js +1 -1
  55. package/package.json +1 -1
  56. package/skills/qgrid/references/ai-sdk-provider-contract.md +34 -2
  57. package/skills/qgrid/references/anthropic-claude-code-runtime.md +3 -0
  58. package/skills/qgrid/references/cli-env-and-server-boot.md +1 -1
  59. package/skills/qgrid/references/decision-rationale.md +10 -1
  60. package/skills/qgrid/references/repo-map.md +2 -1
  61. package/skills/qgrid/references/tool-calling-and-multiturn.md +33 -6
  62. package/skills/qgrid/references/verification-and-debugging.md +16 -1
@@ -49,7 +49,16 @@ Sources:
49
49
  Key decisions:
50
50
 
51
51
  - qgrid tool calling is intentionally implemented through structured-output emulation, not native provider tool use. The provider call returns a structured action with tool calls; the AI SDK loop executes tools and sends follow-up turns.
52
- - Tools and `jsonSchema` are mutually exclusive at the qgrid dispatcher boundary because both need the provider structured-output slot.
52
+ - Tools and `jsonSchema` share one provider structured-output slot by composing
53
+ an action envelope on every turn. Its final `answer` branch embeds the user's
54
+ schema; its `tool_call` branch carries emulated AI SDK calls. This keeps final
55
+ output constrained even when tools are available but never called.
56
+ - Final output is identified by `action: "answer"`, not by tool presence or turn
57
+ count. Structured answers are serialized as JSON text for AI SDK
58
+ `Output.object` parsing, while tools-only callers retain their legacy string
59
+ answer and tolerant parse fallback.
60
+ - AI SDK `toolChoice` remains outside qgrid's wire contract. Do not imply that
61
+ qgrid transports or enforces it.
53
62
  - Tool-call request logs are a multi-step run: create run, append generate/tool steps, then finish run. This makes AI SDK multi-step behavior visible in the dashboard instead of logging only one opaque completion.
54
63
  - Tool results update the existing `tool_call` step by `request_log_id + tool_call_id`. They are not logged as a second unrelated completion row.
55
64
  - The server infers single-turn completion versus an open tool run from context and finish reason. The removed caller-selected `logMode` contract must not be recreated.
@@ -28,7 +28,8 @@ Use this map to orient qgrid work quickly.
28
28
  - Cost/usage accounting: `packages/api/src/utils/providers/common/model-cost.ts`.
29
29
  - Weighted token selection: `packages/api/src/utils/providers/common/smooth-weighted-round-robin.ts`.
30
30
  - Boot order and startup migrations: `packages/api/src/server-bootstrap.ts`, `packages/api/src/startup-migrations.ts`.
31
- - Tool-call emulation: `packages/api/src/application/qgrid/tool-emulation.ts`.
31
+ - Tool-call schema composition: `packages/api/src/application/qgrid/tool-emulation-schema.ts`.
32
+ - Tool-call response decoding: `packages/api/src/application/qgrid/tool-emulation.ts`.
32
33
 
33
34
  ## Web/Sonamu hot spots
34
35
 
@@ -24,6 +24,11 @@ qgrid supports the AI SDK `tools` interface, but it does not use native provider
24
24
  - qgrid maps that structured object back into AI SDK `tool-call` content.
25
25
  - The AI SDK executes the actual tool functions and calls qgrid again with tool results.
26
26
 
27
+ `generateText` and `streamText` default to `stepCountIs(1)`. When an executable
28
+ tool can run before the final answer, callers must set a bounded `stopWhen`
29
+ (for example `stepCountIs(3)`) or the AI SDK stops after the first tool-call
30
+ step and cannot produce the final text or `Output.object` value.
31
+
27
32
  Do not describe this as OpenAI native function calling, Claude native tool use, or Codex/Claude executing client tools. The tools are client-side AI SDK tools requested through structured-output emulation.
28
33
 
29
34
  ## Client Flow
@@ -36,7 +41,9 @@ When `options.tools` contains function tools:
36
41
  2. Convert them with `toQgridTool`.
37
42
  3. Send `tools` in `/api/qgrid/query` or `/api/qgrid/prepareStream`.
38
43
  4. Forward the per-call `logger` switch when request logging is disabled.
39
- 5. Do not send `jsonSchema` response format at the same time. The server infers whether the logged request becomes a multi-step run.
44
+ 5. When a top-level object response format is present, send `jsonSchema` alongside
45
+ `tools`. The server composes both schemas and infers whether the logged request
46
+ becomes a multi-step run.
40
47
 
41
48
  When qgrid responds with `finishReason: "tool-calls"`:
42
49
 
@@ -57,9 +64,10 @@ The registry is keyed per pending run so concurrent `generateText(...tools...)`
57
64
 
58
65
  ## Server Schema Emulation
59
66
 
60
- `packages/api/src/application/qgrid/tool-emulation.ts` builds the tool-call schema.
67
+ `packages/api/src/application/qgrid/tool-emulation-schema.ts` builds the tool-call schema.
68
+ `tool-emulation.ts` decodes the model's action envelope into qgrid answer/tool-call content.
61
69
 
62
- The schema shape is:
70
+ The tools-only schema shape is:
63
71
 
64
72
  ```json
65
73
  {
@@ -83,7 +91,13 @@ The schema explicitly tells the model:
83
91
 
84
92
  `qgrid.dispatcher.ts` strictifies this schema through `buildStrictOutputSchema` before it reaches provider dispatchers.
85
93
 
86
- If tools and `jsonSchema` are both present, dispatcher rejects the request.
94
+ When tools and a user `jsonSchema` are both present, the dispatcher builds the
95
+ same outer envelope on every turn, but replaces `answer: string | null` with
96
+ `answer: <user schema> | null`. The user schema is namespaced under
97
+ `$defs.__qgrid_user_output`, including rebased local JSON pointers, before the
98
+ whole envelope is strictified. This prevents tool availability from disabling
99
+ the final structured-output constraint, including when the model answers without
100
+ calling a tool.
87
101
 
88
102
  ## Provider-Specific Path
89
103
 
@@ -111,9 +125,14 @@ In both providers, native provider tools are not the public abstraction. The pub
111
125
  `applyToolCallEmulation` handles provider text:
112
126
 
113
127
  - No tools: return normal text content.
114
- - Tools present and JSON parse fails: warn and fall back to text with `finishReason: "stop"`.
128
+ - Tools-only mode and JSON parse failure: preserve the legacy warning and text
129
+ fallback with `finishReason: "stop"`.
130
+ - Tools plus a user schema and malformed or incoherent envelope: return an
131
+ explicit structured-output error; do not rescue it as successful text.
115
132
  - `action: "tool_call"`: validate tool names, generate qgrid `toolCallId`, return `finishReason: "tool-calls"`.
116
- - `action: "answer"`: return final text with `finishReason: "stop"`.
133
+ - `action: "answer"` in tools-only mode: return the string answer as final text.
134
+ - `action: "answer"` with a user schema: JSON-serialize the structured `answer`
135
+ as final text so AI SDK can parse and validate `Output.object`.
117
136
 
118
137
  Unknown tool names throw.
119
138
 
@@ -128,6 +147,14 @@ AI SDK multi-step behavior is client-orchestrated:
128
147
 
129
148
  This is different from a provider-native tool loop. Neither Codex nor Claude Code executes the AI SDK tool functions.
130
149
 
150
+ The composed schema is reapplied to tool-result follow-up turns. Final output is
151
+ identified by `action: "answer"` rather than by whether a tool happened to be
152
+ available or called. AI SDK `toolChoice` is not transported or enforced by
153
+ qgrid; the model selects between the envelope's answer and tool-call actions.
154
+
155
+ The combined contract requires qgrid server 2.5.4 and
156
+ `@cartanova/qgrid-ai-sdk` 2.5.4.
157
+
131
158
  OpenAI/Codex follow-ups can reuse the same Codex thread when `runContext.threadCoord` remains valid. For tool-result follow-up turns, qgrid sends delta input containing tool result text to the existing thread; cold fallback injects full history.
132
159
 
133
160
  Anthropic follow-ups do not reuse Claude sessions. qgrid starts a fresh Claude process, replays flattened full history, and sends the tool-result continuation input.
@@ -30,6 +30,7 @@ AI SDK package `@cartanova/qgrid-ai-sdk`:
30
30
  - `pnpm --filter @cartanova/qgrid-ai-sdk test`.
31
31
  - `pnpm --filter @cartanova/qgrid-ai-sdk build`.
32
32
  - `pnpm --filter @cartanova/qgrid-ai-sdk e2e`.
33
+ - `pnpm --filter @cartanova/qgrid-ai-sdk e2e:tools-output`.
33
34
  - `pnpm --filter @cartanova/qgrid-ai-sdk e2e:logger`.
34
35
 
35
36
  CLI package `@cartanova/qgrid-cli`:
@@ -54,7 +55,7 @@ Choose by affected area:
54
55
  | AI SDK logger integration | `packages/ai-sdk/src/logger.test.ts` |
55
56
  | qgrid provider routing and strict schema | `packages/api/src/application/qgrid/qgrid.dispatcher.test.ts` |
56
57
  | conversation/thread reuse routing | `packages/api/src/application/qgrid/conv-routing.test.ts` |
57
- | tool-call emulation | `packages/api/src/application/qgrid/tool-emulation.test.ts` |
58
+ | tool-call emulation | `packages/api/src/application/qgrid/tool-emulation.test.ts`, `tool-emulation-schema.test.ts` |
58
59
  | request-log run lifecycle | `packages/api/src/application/qgrid/qgrid-run-lifecycle.test.ts` |
59
60
  | qgrid frame API behavior | `packages/api/src/application/qgrid/qgrid.frame.test.ts` |
60
61
  | token subscriber and LISTEN/NOTIFY handling | `packages/api/src/application/qgrid/token-subscriber.test.ts` |
@@ -101,6 +102,20 @@ AI SDK structured output:
101
102
  - Env: `QGRID_URL`, `SMOKE_MODEL`, `SMOKE_CASES`, `SMOKE_REPEAT`.
102
103
  - Uses AI SDK 6 `streamText` with `Output.object`; useful for structured-output regressions.
103
104
 
105
+ AI SDK tools plus structured output:
106
+
107
+ - `packages/ai-sdk/e2e/tools-structured-output.ts`
108
+ - This is the public-path release acceptance matrix: `qgrid()` HTTP/SSE,
109
+ `generateText`/`streamText`, OpenAI/Anthropic, direct final answers, and one
110
+ client-tool result followed by `Output.object`.
111
+ - It consumes real provider quota and requires the explicit
112
+ `QGRID_REAL_PROVIDER_ACCEPTANCE=1` opt-in.
113
+ - Uses `QGRID_URL`, `QGRID_ACCEPTANCE_OPENAI_MODEL`, and
114
+ `QGRID_ACCEPTANCE_ANTHROPIC_MODEL`. OpenAI direct-final coverage defaults to
115
+ 10 generate plus 10 stream attempts and can be changed with
116
+ `QGRID_ACCEPTANCE_OPENAI_DIRECT_REPEATS_PER_MODE`. Request logs use the stable
117
+ project name `qgrid-ai-sdk-tools-output-acceptance`.
118
+
104
119
  Image generation:
105
120
 
106
121
  - `packages/api/scripts/smoke-test-image-generation.ts`