@cartanova/qgrid-cli 2.4.6 → 2.4.8

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 (73) hide show
  1. package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +15 -1
  2. package/bundle/dist/application/qgrid/qgrid.dispatcher.js +12 -4
  3. package/bundle/dist/application/qgrid/qgrid.frame.js +20 -1
  4. package/bundle/dist/application/qgrid/qgrid.types.js +38 -2
  5. package/bundle/dist/application/request-log/request-log.model.js +49 -22
  6. package/bundle/dist/application/request-log-step/request-log-step.types.js +8 -1
  7. package/bundle/dist/application/sonamu.generated.js +37 -1
  8. package/bundle/dist/application/sonamu.generated.sso.js +25 -1
  9. package/bundle/dist/i18n/sd.generated.js +13 -1
  10. package/bundle/dist/migrations/20260718180824_alter_request_logs_add5_alter1.js +20 -0
  11. package/bundle/dist/migrations/20260718180825_alter_request_log_steps_add7_alter1.js +22 -0
  12. package/bundle/dist/utils/providers/anthropic/anthropic-constants.js +8 -2
  13. package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +6 -3
  14. package/bundle/dist/utils/providers/anthropic/claude-session.js +11 -7
  15. package/bundle/dist/utils/providers/anthropic/stream-json-adapter.js +117 -7
  16. package/bundle/dist/utils/providers/common/model-cost.js +45 -98
  17. package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +68 -0
  18. package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +14 -0
  19. package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +81 -0
  20. package/bundle/src/application/qgrid/qgrid.dispatcher.ts +16 -9
  21. package/bundle/src/application/qgrid/qgrid.frame.ts +19 -0
  22. package/bundle/src/application/qgrid/qgrid.types.ts +36 -0
  23. package/bundle/src/application/qgrid/tool-emulation.test.ts +1 -0
  24. package/bundle/src/application/request-log/request-log.entity.json +42 -0
  25. package/bundle/src/application/request-log/request-log.model.test.ts +58 -0
  26. package/bundle/src/application/request-log/request-log.model.ts +107 -18
  27. package/bundle/src/application/request-log-step/request-log-step.entity.json +54 -0
  28. package/bundle/src/application/request-log-step/request-log-step.types.ts +7 -0
  29. package/bundle/src/application/sonamu.generated.http +26 -0
  30. package/bundle/src/application/sonamu.generated.sso.ts +24 -0
  31. package/bundle/src/application/sonamu.generated.ts +48 -0
  32. package/bundle/src/i18n/sd.generated.ts +12 -0
  33. package/bundle/src/migrations/20260718180824_alter_request_logs_add5_alter1.ts +25 -0
  34. package/bundle/src/migrations/20260718180825_alter_request_log_steps_add7_alter1.ts +29 -0
  35. package/bundle/src/utils/providers/anthropic/anthropic-constants.test.ts +15 -0
  36. package/bundle/src/utils/providers/anthropic/anthropic-constants.ts +11 -2
  37. package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +7 -2
  38. package/bundle/src/utils/providers/anthropic/claude-session.test.ts +26 -0
  39. package/bundle/src/utils/providers/anthropic/claude-session.ts +16 -4
  40. package/bundle/src/utils/providers/anthropic/stream-json-adapter.test.ts +131 -0
  41. package/bundle/src/utils/providers/anthropic/stream-json-adapter.ts +194 -11
  42. package/bundle/src/utils/providers/common/model-cost.test.ts +136 -2
  43. package/bundle/src/utils/providers/common/model-cost.ts +76 -99
  44. package/bundle/src/utils/providers/common/provider-dispatcher.ts +18 -0
  45. package/bundle/web-dist/client/assets/{index-BOXhNo0k.js → index-CmuPjbCl.js} +3 -3
  46. package/bundle/web-dist/client/assets/{logs-BShH_sut.js → logs-cXOsDli3.js} +1 -1
  47. package/bundle/web-dist/client/assets/{monit-CoEAp5S0.js → monit-B5Edhvy-.js} +1 -1
  48. package/bundle/web-dist/client/assets/{routes-Dr3cGnV3.js → routes-UPWScORY.js} +1 -1
  49. package/bundle/web-dist/client/assets/{sd.generated-D2Y9QeiN.js → sd.generated-DYuKzBY6.js} +1 -1
  50. package/bundle/web-dist/client/assets/{services.generated-CmxXl220.js → services.generated-D_SkWOo-.js} +1 -1
  51. package/bundle/web-dist/client/assets/show-pRp-eZIK.js +30 -0
  52. package/bundle/web-dist/client/assets/{tokens-hP1NecIg.js → tokens-DJlttxCM.js} +1 -1
  53. package/bundle/web-dist/client/assets/{use-update-token-mutation-6J1T9U2-.js → use-update-token-mutation-CpFGLWUl.js} +1 -1
  54. package/bundle/web-dist/client/index.html +2 -2
  55. package/bundle/web-dist/server/assets/{lazyRouteComponent-BlfOh9S3.js → lazyRouteComponent-Cu6IkL8A.js} +1 -1
  56. package/bundle/web-dist/server/assets/{logs-DYly4ipQ.js → logs-Dx2knN2T.js} +10 -7
  57. package/bundle/web-dist/server/assets/{monit-CYyY2S2f.js → monit-DU6PLatf.js} +2 -2
  58. package/bundle/web-dist/server/assets/{routes-Dqu3osXt.js → routes-CTco1oJZ.js} +3 -3
  59. package/bundle/web-dist/server/assets/{sd.generated-CE6D5clm.js → sd.generated-qzuRe35X.js} +12 -0
  60. package/bundle/web-dist/server/assets/{services.generated-DyZUzXiq.js → services.generated-C8q1M41a.js} +1 -1
  61. package/bundle/web-dist/server/assets/{show-BDul8xLb.js → show-B3q8_GDh.js} +47 -4
  62. package/bundle/web-dist/server/assets/{tokens-fzMW4G74.js → tokens-Bvjn15h9.js} +3 -3
  63. package/bundle/web-dist/server/assets/{use-update-token-mutation-BejUW5sw.js → use-update-token-mutation-BlZo6swF.js} +1 -1
  64. package/bundle/web-dist/server/entry-server.generated.js +8 -8
  65. package/package.json +2 -2
  66. package/skills/qgrid/SKILL.md +4 -0
  67. package/skills/qgrid/references/ai-sdk-provider-contract.md +30 -2
  68. package/skills/qgrid/references/anthropic-claude-code-runtime.md +43 -5
  69. package/skills/qgrid/references/decision-rationale.md +2 -0
  70. package/skills/qgrid/references/prompt-cache-and-usage.md +4 -1
  71. package/skills/qgrid/references/request-log-run-lifecycle.md +6 -2
  72. package/skills/qgrid/references/sonamu-api-web-flow.md +13 -0
  73. package/bundle/web-dist/client/assets/show-CXII6Iy7.js +0 -30
@@ -14,7 +14,10 @@ export interface ModelCosts {
14
14
  inputTokens: number;
15
15
  outputTokens: number;
16
16
  cachedInputTokens: number;
17
+ /** TTL breakdown 이 없는 usage 에 적용할 cache write fallback 단가. */
17
18
  cacheCreationInputTokens?: number;
19
+ cacheCreationInputTokens5m?: number;
20
+ cacheCreationInputTokens1h?: number;
18
21
  /**
19
22
  * long-context 할증. 전체 입력 토큰(input_tokens, cache_read 포함)이 threshold 초과 시
20
23
  * 초과분만이 아니라 요청 전체(full session)에 배율 적용.
@@ -29,7 +32,7 @@ export interface ModelCosts {
29
32
 
30
33
  // ── OpenAI — codex app-server 에서 사용 가능한 모델 ─────────────────
31
34
  //
32
- // 가격 출처: https://openai.com/api/pricing (2026-06-11 확인)
35
+ // 가격 출처: https://developers.openai.com/api/docs/models (2026-07-18 확인)
33
36
  // 신모델 출시마다 단가가 바뀌므로(5.2→5.4→5.5) 모델 추가 시 반드시 공식 페이지 재확인해야함
34
37
 
35
38
  // GPT-5.4에서 처음 도입된 long-context 할증 (5.2/5.3-codex는 해당 없음, 5.4-mini/nano는 공식 표에서 long-context 단가 없음)
@@ -97,105 +100,56 @@ const OPENAI_COSTS: Record<string, ModelCosts> = {
97
100
 
98
101
  // ── Anthropic ───────────────────────────────────────────────────────
99
102
 
103
+ function anthropicCosts(inputTokens: number, outputTokens: number): ModelCosts {
104
+ return {
105
+ inputTokens,
106
+ outputTokens,
107
+ cachedInputTokens: inputTokens / 10,
108
+ // Claude Code subscription OAuth 는 1h TTL 을 자동 선택한다. 구버전처럼 응답에
109
+ // TTL breakdown 이 없을 때만 이 1h 단가를 fallback 으로 사용한다.
110
+ cacheCreationInputTokens: inputTokens * 2,
111
+ cacheCreationInputTokens5m: inputTokens * 1.25,
112
+ cacheCreationInputTokens1h: inputTokens * 2,
113
+ };
114
+ }
115
+
100
116
  const ANTHROPIC_COSTS: Record<string, ModelCosts> = {
101
- // Claude Code 는 별도 ttl:"1h" 옵션 없이 실행되므로 fallback 가격표는 5분 cache write(1.25x)를 기준으로 둔다.
102
- // 1시간 cache write 는 input 2x 이지만 현재 qgrid 실행 경로의 기본값이 아니다.
103
- sonnet: {
104
- inputTokens: 3,
105
- outputTokens: 15,
106
- cachedInputTokens: 0.3,
107
- cacheCreationInputTokens: 3.75,
108
- },
109
- "claude-3-5-haiku": {
110
- inputTokens: 0.8,
111
- outputTokens: 4,
112
- cachedInputTokens: 0.08,
113
- cacheCreationInputTokens: 1,
114
- },
115
- "claude-haiku-4-5": {
116
- inputTokens: 1,
117
- outputTokens: 5,
118
- cachedInputTokens: 0.1,
119
- cacheCreationInputTokens: 1.25,
120
- },
121
- "claude-3-5-sonnet": {
122
- inputTokens: 3,
123
- outputTokens: 15,
124
- cachedInputTokens: 0.3,
125
- cacheCreationInputTokens: 3.75,
126
- },
127
- "claude-3-7-sonnet": {
128
- inputTokens: 3,
129
- outputTokens: 15,
130
- cachedInputTokens: 0.3,
131
- cacheCreationInputTokens: 3.75,
132
- },
133
- "claude-sonnet-4": {
134
- inputTokens: 3,
135
- outputTokens: 15,
136
- cachedInputTokens: 0.3,
137
- cacheCreationInputTokens: 3.75,
138
- },
139
- "claude-sonnet-4-5": {
140
- inputTokens: 3,
141
- outputTokens: 15,
142
- cachedInputTokens: 0.3,
143
- cacheCreationInputTokens: 3.75,
144
- },
145
- "claude-sonnet-4-6": {
146
- inputTokens: 3,
147
- outputTokens: 15,
148
- cachedInputTokens: 0.3,
149
- cacheCreationInputTokens: 3.75,
150
- },
151
- "claude-sonnet-4-7": {
152
- inputTokens: 3,
153
- outputTokens: 15,
154
- cachedInputTokens: 0.3,
155
- cacheCreationInputTokens: 3.75,
156
- },
157
- "claude-opus-4": {
158
- inputTokens: 15,
159
- outputTokens: 75,
160
- cachedInputTokens: 1.5,
161
- cacheCreationInputTokens: 18.75,
162
- },
163
- "claude-opus-4-1": {
164
- inputTokens: 15,
165
- outputTokens: 75,
166
- cachedInputTokens: 1.5,
167
- cacheCreationInputTokens: 18.75,
168
- },
169
- "claude-opus-4-5": {
170
- inputTokens: 5,
171
- outputTokens: 25,
172
- cachedInputTokens: 0.5,
173
- cacheCreationInputTokens: 6.25,
174
- },
175
- "claude-opus-4-6": {
176
- inputTokens: 5,
177
- outputTokens: 25,
178
- cachedInputTokens: 0.5,
179
- cacheCreationInputTokens: 6.25,
180
- },
181
- "claude-opus-4-7": {
182
- inputTokens: 5,
183
- outputTokens: 25,
184
- cachedInputTokens: 0.5,
185
- cacheCreationInputTokens: 6.25,
186
- },
187
- "claude-opus-4-8": {
188
- inputTokens: 5,
189
- outputTokens: 25,
190
- cachedInputTokens: 0.5,
191
- cacheCreationInputTokens: 6.25,
192
- },
117
+ "claude-fable-5": anthropicCosts(10, 50),
118
+ sonnet: anthropicCosts(3, 15),
119
+ "claude-3-5-haiku": anthropicCosts(0.8, 4),
120
+ "claude-haiku-4-5": anthropicCosts(1, 5),
121
+ "claude-3-5-sonnet": anthropicCosts(3, 15),
122
+ "claude-3-7-sonnet": anthropicCosts(3, 15),
123
+ "claude-sonnet-4": anthropicCosts(3, 15),
124
+ "claude-sonnet-4-5": anthropicCosts(3, 15),
125
+ "claude-sonnet-4-6": anthropicCosts(3, 15),
126
+ "claude-sonnet-4-7": anthropicCosts(3, 15),
127
+ "claude-opus-4": anthropicCosts(15, 75),
128
+ "claude-opus-4-1": anthropicCosts(15, 75),
129
+ "claude-opus-4-5": anthropicCosts(5, 25),
130
+ "claude-opus-4-6": anthropicCosts(5, 25),
131
+ "claude-opus-4-7": anthropicCosts(5, 25),
132
+ "claude-opus-4-8": anthropicCosts(5, 25),
193
133
  };
194
134
 
135
+ // Anthropic 공식 introductory pricing: 2026-08-31까지 $2/$10, 이후 $3/$15.
136
+ // qgrid 는 요청 시점에 계산하므로 배포를 다시 하지 않아도 2026-09-01 UTC부터 표준 단가로 전환한다.
137
+ const CLAUDE_SONNET_5_INTRO_PRICING_END_MS = Date.UTC(2026, 8, 1);
138
+ const CLAUDE_SONNET_5_INTRO_COSTS = anthropicCosts(2, 10);
139
+ const CLAUDE_SONNET_5_STANDARD_COSTS = anthropicCosts(3, 15);
140
+
141
+ // gpt-5.3-codex-spark 는 research preview 로 공식 token 단가가 아직 final 이 아니다.
142
+ // 지원 타입은 유지하되, 공식 단가가 공개될 때까지 아래 generic estimate 로 계산한다.
143
+ // @see https://help.openai.com/en/articles/20001106-codex-rate-card
195
144
  const DEFAULT_COSTS: ModelCosts = { inputTokens: 3, outputTokens: 15, cachedInputTokens: 0.3 };
196
145
 
197
- export function getModelCosts(model: string): ModelCosts {
198
- const normalizedModel = model.replace(/\[1m\]$/i, "");
146
+ export function getModelCosts(model: string, atMs = Date.now()): ModelCosts {
147
+ const normalizedModel = (model.split("/").pop() ?? model).replace(/\[1m\]$/i, "");
148
+ if (normalizedModel === "claude-sonnet-5") {
149
+ return atMs < CLAUDE_SONNET_5_INTRO_PRICING_END_MS
150
+ ? CLAUDE_SONNET_5_INTRO_COSTS
151
+ : CLAUDE_SONNET_5_STANDARD_COSTS;
152
+ }
199
153
  return OPENAI_COSTS[normalizedModel] ?? ANTHROPIC_COSTS[normalizedModel] ?? DEFAULT_COSTS;
200
154
  }
201
155
 
@@ -206,11 +160,26 @@ export function calculateCostUsd(
206
160
  outputTokens: number;
207
161
  cachedInputTokens?: number;
208
162
  cacheCreationInputTokens?: number;
163
+ cacheCreationInputTokens5m?: number;
164
+ cacheCreationInputTokens1h?: number;
209
165
  },
166
+ atMs = Date.now(),
210
167
  ): number {
211
- const costs = getModelCosts(model);
168
+ const costs = getModelCosts(model, atMs);
212
169
  const cachedInput = usage.cachedInputTokens ?? 0;
213
- const cacheCreationInput = usage.cacheCreationInputTokens ?? 0;
170
+ const cacheCreationInput5m = Math.max(usage.cacheCreationInputTokens5m ?? 0, 0);
171
+ const cacheCreationInput1h = Math.max(usage.cacheCreationInputTokens1h ?? 0, 0);
172
+ const cacheCreationInput = Math.max(
173
+ usage.cacheCreationInputTokens ?? 0,
174
+ cacheCreationInput5m + cacheCreationInput1h,
175
+ );
176
+ const classifiedCacheCreationInput5m = Math.min(cacheCreationInput5m, cacheCreationInput);
177
+ const classifiedCacheCreationInput1h = Math.min(
178
+ cacheCreationInput1h,
179
+ cacheCreationInput - classifiedCacheCreationInput5m,
180
+ );
181
+ const unclassifiedCacheCreationInput =
182
+ cacheCreationInput - classifiedCacheCreationInput5m - classifiedCacheCreationInput1h;
214
183
  const nonCachedInput = Math.max(usage.inputTokens - cachedInput - cacheCreationInput, 0);
215
184
 
216
185
  // long-context 할증: 전체 입력(input_tokens, cache 포함)이 threshold 초과 시 요청 전체에 배율 적용
@@ -218,15 +187,23 @@ export function calculateCostUsd(
218
187
  const isLongContext = lc !== undefined && usage.inputTokens > lc.threshold;
219
188
  const inputRate = costs.inputTokens * (isLongContext ? lc.inputMultiplier : 1);
220
189
  const cachedRate = costs.cachedInputTokens * (isLongContext ? lc.cachedInputMultiplier : 1);
221
- const cacheCreationRate =
190
+ const cacheCreationFallbackRate =
222
191
  (costs.cacheCreationInputTokens ?? costs.inputTokens) *
223
192
  (isLongContext ? lc.inputMultiplier : 1);
193
+ const cacheCreation5mRate =
194
+ (costs.cacheCreationInputTokens5m ?? costs.cacheCreationInputTokens ?? costs.inputTokens) *
195
+ (isLongContext ? lc.inputMultiplier : 1);
196
+ const cacheCreation1hRate =
197
+ (costs.cacheCreationInputTokens1h ?? costs.cacheCreationInputTokens ?? costs.inputTokens) *
198
+ (isLongContext ? lc.inputMultiplier : 1);
224
199
  const outputRate = costs.outputTokens * (isLongContext ? lc.outputMultiplier : 1);
225
200
 
226
201
  return (
227
202
  (nonCachedInput / 1_000_000) * inputRate +
228
203
  (usage.outputTokens / 1_000_000) * outputRate +
229
204
  (cachedInput / 1_000_000) * cachedRate +
230
- (cacheCreationInput / 1_000_000) * cacheCreationRate
205
+ (unclassifiedCacheCreationInput / 1_000_000) * cacheCreationFallbackRate +
206
+ (classifiedCacheCreationInput5m / 1_000_000) * cacheCreation5mRate +
207
+ (classifiedCacheCreationInput1h / 1_000_000) * cacheCreation1hRate
231
208
  );
232
209
  }
@@ -13,6 +13,8 @@ import { type UserInput } from "../../../codex-protocol/v2/UserInput";
13
13
  // provider 전용 cache write 세부 필드는 여기서 확장해 보존한다.
14
14
  export type ProviderTokenUsageBreakdown = TokenUsageBreakdown & {
15
15
  cacheCreationInputTokens?: number;
16
+ cacheCreationInputTokens5m?: number;
17
+ cacheCreationInputTokens1h?: number;
16
18
  };
17
19
 
18
20
  // thread 재사용 라우팅 좌표. 상위(qgrid.dispatcher)에서 conv 핸들 검증을 통과한 경우에만 전달.
@@ -30,6 +32,19 @@ export interface GeneratedImage {
30
32
  revisedPrompt: string | null;
31
33
  }
32
34
 
35
+ // Provider/런타임이 요청 모델 대신 다른 모델로 실제 응답을 생성한 이력.
36
+ // 현재 Claude Code 의 Fable refusal → Opus 안전 fallback 을 표현하며, 향후 provider
37
+ // fallback 도 같은 계약으로 올릴 수 있다.
38
+ export interface ModelFallback {
39
+ trigger: "refusal";
40
+ fromModel: string;
41
+ toModel: string;
42
+ category?: string;
43
+ explanation?: string;
44
+ }
45
+
46
+ export type CostSource = "provider" | "pricing_table" | "mixed";
47
+
33
48
  export interface GenerateRequest {
34
49
  // 미지정이면 dispatcher 가 provider 별 default 를 적용한다(Anthropic: ANTHROPIC_DEFAULT_MODEL).
35
50
  // OpenAI 경로는 항상 prefix split 후 canonical model 을 넘기므로 영향 없음.
@@ -65,7 +80,10 @@ export interface GenerateResult {
65
80
  // Provider 가 직접 산출한 비용. Anthropic Claude Code 는 total_cost_usd 를 주므로 이 값을
66
81
  // 우선 사용하고, 없으면 상위가 모델별 가격표로 계산한다.
67
82
  costUsd?: number;
83
+ // model 은 실제 응답을 생성한 serving model. fallback 이 없으면 requestedModel 과 같다.
68
84
  model: string;
85
+ requestedModel?: string;
86
+ modelFallbacks?: Array<ModelFallback>;
69
87
  // 이번 turn 이 사용한 thread 좌표. 상위가 conv 핸들을 발급/갱신하는 데 쓴다.
70
88
  threadCoord: ReuseThreadCoord;
71
89
  // 이미지 turn 에서만 채워짐(OpenAI 경로). 완성 이미지가 없으면 undefined.