@cartanova/qgrid-cli 2.10.9 → 2.10.10

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 (49) hide show
  1. package/bundle/dist/application/qgrid/qgrid-response-format.js +2 -2
  2. package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +4 -2
  3. package/bundle/dist/application/request-log/request-log.model.js +2 -1
  4. package/bundle/dist/application/request-log/request-log.types.js +8 -2
  5. package/bundle/dist/application/sonamu.generated.js +9 -1
  6. package/bundle/dist/application/sonamu.generated.sso.js +2 -1
  7. package/bundle/dist/i18n/sd.generated.js +2 -1
  8. package/bundle/dist/migrations/20261018215031_alter_request_logs_add1_alter1.js +15 -0
  9. package/bundle/src/application/qgrid/qgrid-response-format.ts +1 -1
  10. package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +14 -0
  11. package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +3 -0
  12. package/bundle/src/application/request-log/request-log.entity.json +8 -0
  13. package/bundle/src/application/request-log/request-log.model.ts +3 -0
  14. package/bundle/src/application/request-log/request-log.types.ts +11 -0
  15. package/bundle/src/application/sonamu.generated.http +2 -0
  16. package/bundle/src/application/sonamu.generated.sso.ts +1 -0
  17. package/bundle/src/application/sonamu.generated.ts +14 -0
  18. package/bundle/src/i18n/sd.generated.ts +1 -0
  19. package/bundle/src/migrations/20261018215031_alter_request_logs_add1_alter1.ts +15 -0
  20. package/bundle/web-dist/client/assets/{index-CrXKu_J8.js → index-DZwzUfI-.js} +4 -4
  21. package/bundle/web-dist/client/assets/{logs-B2SmWJXA.js → logs-Cog79DU5.js} +1 -1
  22. package/bundle/web-dist/client/assets/{monit-D-JwXXoA.js → monit-2auznBys.js} +1 -1
  23. package/bundle/web-dist/client/assets/{routes-C5r4gTvY.js → routes-B0lTeLK-.js} +1 -1
  24. package/bundle/web-dist/client/assets/{services.generated-BsieU37H.js → services.generated-NP-ValHd.js} +1 -1
  25. package/bundle/web-dist/client/assets/{settings-D3tDSAck.js → settings-D8ZxZGSJ.js} +1 -1
  26. package/bundle/web-dist/client/assets/{show-Cah_kUKC.js → show-CFSERlnM.js} +2 -2
  27. package/bundle/web-dist/client/assets/{tokens-DU2Iyxxd.js → tokens-CZXUyI7O.js} +1 -1
  28. package/bundle/web-dist/client/assets/{use-oauth-login-flow-D0UaR9_e.js → use-oauth-login-flow-hboOs3wG.js} +1 -1
  29. package/bundle/web-dist/client/assets/{use-update-token-mutation-DAq0F8p-.js → use-update-token-mutation-BQHS0byG.js} +1 -1
  30. package/bundle/web-dist/client/index.html +2 -2
  31. package/bundle/web-dist/server/assets/{lazyRouteComponent-Dtd0NR4r.js → lazyRouteComponent-CgBdabgd.js} +2 -2
  32. package/bundle/web-dist/server/assets/{logs-l91avYif.js → logs-BMyR98rU.js} +4 -4
  33. package/bundle/web-dist/server/assets/{monit-DvzribSE.js → monit-ZPt66W5M.js} +3 -3
  34. package/bundle/web-dist/server/assets/{plus-KZrECewT.js → plus-BZ9I0VgC.js} +1 -1
  35. package/bundle/web-dist/server/assets/{react-dom-B4a6-uuR.js → react-dom-Ds75e4Jl.js} +1 -1
  36. package/bundle/web-dist/server/assets/{refresh-cw-BND93JrF.js → refresh-cw-CztCFis-.js} +1 -1
  37. package/bundle/web-dist/server/assets/{request-model-CbqfnQOJ.js → request-model-DjGldb-h.js} +1 -1
  38. package/bundle/web-dist/server/assets/{routes-BAPWTizT.js → routes-Ct-k7nBA.js} +4 -4
  39. package/bundle/web-dist/server/assets/{services.generated-CEbGjsI0.js → services.generated-BA4AcAf5.js} +1 -0
  40. package/bundle/web-dist/server/assets/{settings-BZR5HSAL.js → settings-CBUZ47Xx.js} +3 -3
  41. package/bundle/web-dist/server/assets/{show-CxVZTAdv.js → show-LSFIzvO2.js} +11 -7
  42. package/bundle/web-dist/server/assets/{tokens-D1hb4eKk.js → tokens-DxrBW512.js} +4 -4
  43. package/bundle/web-dist/server/assets/{use-oauth-login-flow-Cvdy0zF8.js → use-oauth-login-flow-Gn8flMK5.js} +1 -1
  44. package/bundle/web-dist/server/assets/{use-update-token-mutation-CfYmk_4_.js → use-update-token-mutation-pkArIzCP.js} +1 -1
  45. package/bundle/web-dist/server/entry-server.generated.js +18 -10
  46. package/package.json +1 -1
  47. package/skills/qgrid/references/decision-rationale.md +1 -1
  48. package/skills/qgrid/references/request-log-run-lifecycle.md +1 -1
  49. package/skills/qgrid/references/sonamu-api-web-flow.md +1 -1
@@ -1,8 +1,8 @@
1
- import { A as require_react, E as useQuery, X as __toESM, i as RequestLogStepService, k as require_jsx_runtime, l as isSonamuError, q as __commonJSMin, r as RequestLogService } from "./services.generated-CEbGjsI0.js";
2
- import { a as Link } from "./lazyRouteComponent-Dtd0NR4r.js";
1
+ import { A as require_react, E as useQuery, X as __toESM, i as RequestLogStepService, k as require_jsx_runtime, l as isSonamuError, q as __commonJSMin, r as RequestLogService } from "./services.generated-BA4AcAf5.js";
2
+ import { a as Link } from "./lazyRouteComponent-CgBdabgd.js";
3
3
  import { c as lucideX, d as Markdown, t as Route, u as remarkGfm } from "../entry-server.generated.js";
4
4
  import { n as formatMicroUsd, t as cacheHitRate } from "./cost-eEHeTRT5.js";
5
- import { n as lucideZap, t as requestModelDisplay } from "./request-model-CbqfnQOJ.js";
5
+ import { n as lucideZap, t as requestModelDisplay } from "./request-model-DjGldb-h.js";
6
6
  //#region ../../node_modules/.pnpm/@babel+runtime@7.29.2/node_modules/@babel/runtime/helpers/extends.js
7
7
  var require_extends = /* @__PURE__ */ __commonJSMin(((exports, module) => {
8
8
  function _extends() {
@@ -2361,9 +2361,10 @@ function ToolInputImages({ images }) {
2361
2361
  })
2362
2362
  })] });
2363
2363
  }
2364
- function RequestInputImages({ stepId }) {
2365
- const { data: detail } = RequestLogStepService.useRequestLogStep("I", stepId ?? 0, { enabled: stepId !== null });
2366
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToolInputImages, { images: getToolInputImages(detail ? safeParseJson(detail.tool_args) : null) });
2364
+ function RequestInputImages({ images, stepId }) {
2365
+ const { data: detail } = RequestLogStepService.useRequestLogStep("I", stepId ?? 0, { enabled: images === null && stepId !== null });
2366
+ const args = detail ? safeParseJson(detail.tool_args) : null;
2367
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToolInputImages, { images: images ?? getToolInputImages(args) });
2367
2368
  }
2368
2369
  function ToolCallItem({ entry }) {
2369
2370
  const hasError = !!entry.error;
@@ -2921,7 +2922,10 @@ function RequestDetail({ id }) {
2921
2922
  text: data.user_prompt ?? "null",
2922
2923
  markdown: true
2923
2924
  })]
2924
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequestInputImages, { stepId: firstImageGenerationStepId })]
2925
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequestInputImages, {
2926
+ images: data.input_images,
2927
+ stepId: firstImageGenerationStepId
2928
+ })]
2925
2929
  })
2926
2930
  })]
2927
2931
  });
@@ -1,8 +1,8 @@
1
- import { A as require_react, O as useQueryClient, X as __toESM, k as require_jsx_runtime, n as QgridService, o as TokenService } from "./services.generated-CEbGjsI0.js";
1
+ import { A as require_react, O as useQueryClient, X as __toESM, k as require_jsx_runtime, n as QgridService, o as TokenService } from "./services.generated-BA4AcAf5.js";
2
2
  import { f as lucideKeyRound, o as Q } from "../entry-server.generated.js";
3
- import { t as useUpdateTokenMutation } from "./use-update-token-mutation-CfYmk_4_.js";
4
- import { n as OAuthCodeEntry, t as useOAuthLoginFlow } from "./use-oauth-login-flow-Cvdy0zF8.js";
5
- import { t as lucidePlus } from "./plus-KZrECewT.js";
3
+ import { t as useUpdateTokenMutation } from "./use-update-token-mutation-pkArIzCP.js";
4
+ import { n as OAuthCodeEntry, t as useOAuthLoginFlow } from "./use-oauth-login-flow-Gn8flMK5.js";
5
+ import { t as lucidePlus } from "./plus-BZ9I0VgC.js";
6
6
  //#region src/components/qgrid/AddTokenModal.tsx
7
7
  var import_react = /* @__PURE__ */ __toESM(require_react(), 1);
8
8
  var import_jsx_runtime = require_jsx_runtime();
@@ -1,4 +1,4 @@
1
- import { A as require_react, O as useQueryClient, X as __toESM, k as require_jsx_runtime, n as QgridService, o as TokenService } from "./services.generated-CEbGjsI0.js";
1
+ import { A as require_react, O as useQueryClient, X as __toESM, k as require_jsx_runtime, n as QgridService, o as TokenService } from "./services.generated-BA4AcAf5.js";
2
2
  import { o as Q } from "../entry-server.generated.js";
3
3
  //#region src/components/qgrid/OAuthCodeEntry.tsx
4
4
  var import_react = /* @__PURE__ */ __toESM(require_react(), 1);
@@ -1,4 +1,4 @@
1
- import { T as useMutation, n as QgridService } from "./services.generated-CEbGjsI0.js";
1
+ import { T as useMutation, n as QgridService } from "./services.generated-BA4AcAf5.js";
2
2
  //#region src/services/token/use-update-token-mutation.ts
3
3
  function useUpdateTokenMutation() {
4
4
  return useMutation({ mutationFn: ({ id, name, quotaThreshold, weight, keepaliveEnabled }) => QgridService.updateToken(id, name, quotaThreshold, weight, keepaliveEnabled) });
@@ -1,6 +1,6 @@
1
- import { A as require_react, B as matchQuery, C as union, D as QueryClientProvider, F as notifyManager, G as focusManager, H as partialMatchKey, I as functionalUpdate, J as __exportAll, K as Subscribable, L as hashKey, M as infiniteQueryBehavior, N as Query, P as onlineManager, R as hashQueryKeyByOptions, S as string$2, U as resolveStaleTime, V as noop$1, W as skipToken, X as __toESM, Y as __require, _ as custom, b as number$1, c as fetch$1, d as SD, f as SUPPORTED_LOCALES, g as boolean$1, h as array, j as Mutation, k as require_jsx_runtime, m as _enum, n as QgridService, o as TokenService, p as setLocale, q as __commonJSMin, s as SonamuQueryMode, u as zArrayable, v as date, w as unknown, x as object, y as int, z as matchMutation } from "./assets/services.generated-CEbGjsI0.js";
2
- import { A as decodePath, C as findRouteMatch, D as createLRUCache, E as processRouteTree, F as last, I as replaceEqualDeep, M as findLast, N as functionalUpdate$1, O as invariant, P as isPromise, S as findFlatMatch, T as processRouteMasks, _ as interpolatePath, a as Link$1, b as trimPath, c as usePrevious$1, d as useRouter, f as getRouterContext, g as cleanPath, h as isNotFound, i as createRootRouteWithContext, j as deepEqual$2, k as createControlledPromise, l as matchContext, m as rootRouteId, n as createFileRoute, p as warning, r as createLazyFileRoute, s as useLayoutEffect$3, t as lazyRouteComponent, u as useRouterState, v as joinPaths, w as findSingleMatch, x as trimPathRight, y as resolvePath } from "./assets/lazyRouteComponent-Dtd0NR4r.js";
3
- import { n as require_shim, t as require_react_dom } from "./assets/react-dom-B4a6-uuR.js";
1
+ import { A as require_react, B as matchQuery, C as union, D as QueryClientProvider, F as notifyManager, G as focusManager, H as partialMatchKey, I as functionalUpdate, J as __exportAll, K as Subscribable, L as hashKey, M as infiniteQueryBehavior, N as Query, P as onlineManager, R as hashQueryKeyByOptions, S as string$2, U as resolveStaleTime, V as noop$1, W as skipToken, X as __toESM, Y as __require, _ as custom, b as number$1, c as fetch$1, d as SD, f as SUPPORTED_LOCALES, g as boolean$1, h as array, j as Mutation, k as require_jsx_runtime, m as _enum, n as QgridService, o as TokenService, p as setLocale, q as __commonJSMin, s as SonamuQueryMode, u as zArrayable, v as date, w as unknown, x as object, y as int, z as matchMutation } from "./assets/services.generated-BA4AcAf5.js";
2
+ import { A as decodePath, C as findRouteMatch, D as createLRUCache, E as processRouteTree, F as last, I as replaceEqualDeep, M as findLast, N as functionalUpdate$1, O as invariant, P as isPromise, S as findFlatMatch, T as processRouteMasks, _ as interpolatePath, a as Link$1, b as trimPath, c as usePrevious$1, d as useRouter, f as getRouterContext, g as cleanPath, h as isNotFound, i as createRootRouteWithContext, j as deepEqual$2, k as createControlledPromise, l as matchContext, m as rootRouteId, n as createFileRoute, p as warning, r as createLazyFileRoute, s as useLayoutEffect$3, t as lazyRouteComponent, u as useRouterState, v as joinPaths, w as findSingleMatch, x as trimPathRight, y as resolvePath } from "./assets/lazyRouteComponent-CgBdabgd.js";
3
+ import { n as require_shim, t as require_react_dom } from "./assets/react-dom-Ds75e4Jl.js";
4
4
  import minpath from "node:path";
5
5
  import minproc from "node:process";
6
6
  import { fileURLToPath as urlToPath } from "node:url";
@@ -46874,7 +46874,7 @@ function ChatWidget() {
46874
46874
  }
46875
46875
  //#endregion
46876
46876
  //#region src/components/Sidebar.tsx
46877
- var qgridVersion = "2.10.9";
46877
+ var qgridVersion = "2.10.10";
46878
46878
  function Sidebar({ className }) {
46879
46879
  const pathname = useRouterState({ select: (s) => s.location.pathname });
46880
46880
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("aside", {
@@ -68752,15 +68752,15 @@ function RootComponent() {
68752
68752
  }
68753
68753
  //#endregion
68754
68754
  //#region src/routes/tokens.tsx
68755
- var $$splitComponentImporter$5 = () => import("./assets/tokens-D1hb4eKk.js");
68755
+ var $$splitComponentImporter$5 = () => import("./assets/tokens-DxrBW512.js");
68756
68756
  var Route$5 = createFileRoute("/tokens")({ component: lazyRouteComponent($$splitComponentImporter$5, "component") });
68757
68757
  //#endregion
68758
68758
  //#region src/routes/settings.tsx
68759
- var $$splitComponentImporter$4 = () => import("./assets/settings-BZR5HSAL.js");
68759
+ var $$splitComponentImporter$4 = () => import("./assets/settings-CBUZ47Xx.js");
68760
68760
  var Route$4 = createFileRoute("/settings")({ component: lazyRouteComponent($$splitComponentImporter$4, "component") });
68761
68761
  //#endregion
68762
68762
  //#region src/routes/monit.tsx
68763
- var $$splitComponentImporter$3 = () => import("./assets/monit-DvzribSE.js");
68763
+ var $$splitComponentImporter$3 = () => import("./assets/monit-ZPt66W5M.js");
68764
68764
  var monitSearchSchema = object({ level: _enum([
68765
68765
  "all",
68766
68766
  "warn",
@@ -68785,6 +68785,12 @@ var HistoryItems = array(object({
68785
68785
  call_id: string$2().optional(),
68786
68786
  output: string$2().optional()
68787
68787
  }));
68788
+ var InputImages = array(object({
68789
+ mediaType: string$2().optional(),
68790
+ data: string$2().optional(),
68791
+ url: string$2().optional(),
68792
+ byteSize: number$1().optional()
68793
+ }));
68788
68794
  var TokenCredentials = union([object({
68789
68795
  accessToken: string$2(),
68790
68796
  refreshToken: string$2(),
@@ -68868,6 +68874,7 @@ object({
68868
68874
  service_tier: string$2().max(20).nullable(),
68869
68875
  effort: string$2().max(10).nullable(),
68870
68876
  history: HistoryItems.nullable(),
68877
+ input_images: InputImages.nullable(),
68871
68878
  tools: ToolDefinitions.nullable(),
68872
68879
  json_schema: string$2().nullable(),
68873
68880
  status: RequestLogStatus,
@@ -68998,6 +69005,7 @@ object({
68998
69005
  effort: string$2().max(10).nullable(),
68999
69006
  service_tier: string$2().max(20).nullable(),
69000
69007
  history: HistoryItems.nullable(),
69008
+ input_images: InputImages.nullable(),
69001
69009
  tools: ToolDefinitions.nullable(),
69002
69010
  status: RequestLogStatus,
69003
69011
  response_json_ok: boolean$1().nullable(),
@@ -69140,7 +69148,7 @@ object({
69140
69148
  _enum(["A"]);
69141
69149
  //#endregion
69142
69150
  //#region src/routes/logs.tsx
69143
- var $$splitComponentImporter$2 = () => import("./assets/logs-l91avYif.js");
69151
+ var $$splitComponentImporter$2 = () => import("./assets/logs-BMyR98rU.js");
69144
69152
  var logsSearchSchema = object({
69145
69153
  token: string$2().optional(),
69146
69154
  project: string$2().optional(),
@@ -69154,11 +69162,11 @@ var Route$2 = createFileRoute("/logs")({
69154
69162
  });
69155
69163
  //#endregion
69156
69164
  //#region src/routes/index.tsx
69157
- var $$splitComponentImporter$1 = () => import("./assets/routes-BAPWTizT.js");
69165
+ var $$splitComponentImporter$1 = () => import("./assets/routes-Ct-k7nBA.js");
69158
69166
  var Route$1 = createFileRoute("/")({ component: lazyRouteComponent($$splitComponentImporter$1, "component") });
69159
69167
  //#endregion
69160
69168
  //#region src/routes/requests/show.tsx
69161
- var $$splitComponentImporter = () => import("./assets/show-CxVZTAdv.js");
69169
+ var $$splitComponentImporter = () => import("./assets/show-LSFIzvO2.js");
69162
69170
  var showSearchSchema = object({ id: number$1() });
69163
69171
  var Route = createFileRoute("/requests/show")({
69164
69172
  validateSearch: showSearchSchema,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cartanova/qgrid-cli",
3
- "version": "2.10.9",
3
+ "version": "2.10.10",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/cartanova-ai/qgrid"
@@ -237,7 +237,7 @@ Key decisions:
237
237
  - qgrid performs preflight capability/model gates. Raw `imageGeneration: true` requires an image; `"auto"` allows normal text replies but still rejects attempted image generation without a completed image. Public `generateImage` requires one direct Images output per provider call; AI SDK batches requests for `n` outputs.
238
238
  - Raw returned images are inline base64 content parts. The image SDK maps them to AI SDK `image`/`images` and takes references through standard `prompt: { text, images }`, with JSON data URL size guarding and HTTPS reference URL support. The language SDK forwards user-message images to `openai/` models as image input (image→text) and drops other image parts with an AI SDK `unsupported` warning.
239
239
  - Raw/server `imageGenerationOptions` supports quality, size, and background. The public image SDK uses flat `QgridImageProviderOptions` and standard top-level `size`. The subscription backend can ignore size and quality hints. Put desired ratios in the prompt, report observed output settings, and never silently resize. Reported image usage is priced at public token rates; without it, use the requested quality/size table with a default-size price for auto/custom hints. Preserve observed settings separately from pricing assumptions. No background-removal fallback is allowed.
240
- - qgrid does not manage generated or reference images as durable assets through a `generated_images` table or object-storage layer. Current request logs can still contain inline image data URLs for inspection and synthetic `image_generation` tool-call steps; reference input images live in the first synthetic step's `tool_args.inputImages`.
240
+ - qgrid does not manage generated or reference images as durable assets through a `generated_images` table or object-storage layer. Current request logs can still contain inline image data URLs for inspection and synthetic `image_generation` tool-call steps; current-turn input images (image→text and image references) live in `request_logs.input_images`; older image-generation logs keep them only in the first synthetic step's `tool_args.inputImages`.
241
241
  - Image cost is stored separately in `request_logs.image_cost_usd`; `request_logs.cost_usd` remains the Codex driver model token cost. Image costs use reported image usage at public token rates, or per-image quality/size estimates when usage is absent. Auto/custom sizes fall back to the 1536x1024 price; omitted quality uses medium. Rows and totals display combined costs as dollar amounts without Cost labels, without Known/Estimated labels or pricing disclaimers. Existing stored null costs are not backfilled; `totalCost.unknownImageCostCount` remains for API compatibility.
242
242
  - Inspect current plans, tests, and implementation before changing behavior; the Codex tool surface can change underneath qgrid.
243
243
 
@@ -98,7 +98,7 @@ For `imageGeneration: "auto"`, set `is_image_generation` only when returned cont
98
98
 
99
99
  If the auto image stage fails or is cancelled after the chat driver has completed, preserve the completed driver result as internal failure metadata. The frame converts it with the same usage/pricing mapper used on success; terminal logging writes one generate step before aggregating the run and retains the actual/requested model and token. The parent remains `error` or `aborted` with the original error message. Do not write a completed image step, invent an image cost, expose failure metadata in the HTTP error, or record this step again on success. A driver that never completed and a direct image-only call have no completed chat usage to retain. `logger: false` still creates no logs. Log-writing failures must not replace the original generation failure.
100
100
 
101
- Reference images for image generation are not stored in `request_logs.user_prompt`; that field remains the text prompt. For inspection in the detail view, qgrid stores reference image metadata/base64 in the synthetic `image_generation` step's `tool_args.inputImages`. If Codex returns multiple image outputs, store `inputImages` only on the first synthetic image tool step so multi-output logs do not duplicate the same input payload on every output.
101
+ Input images are not stored in `request_logs.user_prompt`; that field remains the text prompt. `beforeQuery` stores the current turn's `args.input` images on the run as `request_logs.input_images` (`{ mediaType, data, byteSize }` or `{ url }`), for text and image runs alike. Earlier-turn images in `history` stay in `request_logs.history`. For inspection in the detail view, qgrid stores reference image metadata/base64 in the synthetic `image_generation` step's `tool_args.inputImages`. If Codex returns multiple image outputs, store `inputImages` only on the first synthetic image tool step so multi-output logs do not duplicate the same input payload on every output.
102
102
 
103
103
  ## Structured output fields
104
104
 
@@ -78,7 +78,7 @@ Chat model presets: the model `<select>` lists the served subset of `QgridSuppor
78
78
 
79
79
  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.
80
80
 
81
- Reference input images for image generation render in the detail view under the user prompt from the first synthetic `image_generation` step's `tool_args.inputImages`. Keep the prompt itself text-only, redact large base64 in request JSON views, and avoid rendering duplicate input previews for multi-output image turns.
81
+ Current-turn input images render in the detail view under the user prompt from `request_logs.input_images` (subset `A` only, not the list subset). Logs created before that column fall back to the first synthetic `image_generation` step's `tool_args.inputImages`. Keep the prompt itself text-only, redact large base64 in request JSON views, and avoid rendering duplicate input previews for multi-output image turns.
82
82
 
83
83
  ## Verification
84
84