@cartanova/qgrid-cli 2.9.9 → 2.10.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/application/qgrid/qgrid.frame.js +7 -2
- package/bundle/dist/application/qgrid/qgrid.types.js +3 -1
- package/bundle/dist/utils/providers/common/model-cost.js +9 -1
- package/bundle/src/application/qgrid/qgrid.frame.test.ts +3 -2
- package/bundle/src/application/qgrid/qgrid.frame.ts +9 -3
- package/bundle/src/application/qgrid/qgrid.types.ts +2 -0
- package/bundle/src/utils/providers/common/effort.test.ts +1 -0
- package/bundle/src/utils/providers/common/model-cost.test.ts +4 -0
- package/bundle/src/utils/providers/common/model-cost.ts +12 -0
- package/bundle/src/utils/providers/openai/openai-dispatcher.test.ts +1 -0
- package/bundle/web-dist/client/assets/{index-D8VwLsuq.js → index-BfwrIBHs.js} +3 -3
- package/bundle/web-dist/client/assets/{logs-_T8KV5ne.js → logs-Brit-LqB.js} +1 -1
- package/bundle/web-dist/client/assets/{monit-DRCrtO2j.js → monit-DrYZkisv.js} +1 -1
- package/bundle/web-dist/client/assets/{routes-5A6mia6C.js → routes-C8Y6olae.js} +1 -1
- package/bundle/web-dist/client/assets/{settings-BpP9WVFI.js → settings-CdVqtDQ5.js} +1 -1
- package/bundle/web-dist/client/assets/{show-D5ifZXdy.js → show-2B2X9MkO.js} +1 -1
- package/bundle/web-dist/client/assets/{tokens-Cfe6WvLK.js → tokens-CxXtdk9o.js} +1 -1
- package/bundle/web-dist/client/assets/{use-oauth-login-flow-BTLUGhwh.js → use-oauth-login-flow-B9EqnwY9.js} +1 -1
- package/bundle/web-dist/client/index.html +1 -1
- package/bundle/web-dist/server/entry-server.generated.js +3 -3
- package/package.json +1 -1
- package/skills/qgrid/SKILL.md +6 -0
- package/skills/qgrid/references/ai-sdk-provider-contract.md +4 -0
- package/skills/qgrid/references/openai-codex-runtime.md +16 -2
- package/skills/qgrid/references/request-log-run-lifecycle.md +2 -0
- package/skills/qgrid/references/sonamu-api-web-flow.md +1 -1
|
@@ -271,6 +271,7 @@ describe("QgridFrame.query request logging", () => {
|
|
|
271
271
|
expect(beforeQueryMock).toHaveBeenCalledWith(args);
|
|
272
272
|
expect(afterQueryMock).toHaveBeenCalledWith(41, 0, args, expect.objectContaining({ text: "hello" }));
|
|
273
273
|
expect(result.runContext).toEqual(queryOutput().runContext);
|
|
274
|
+
expect(result.requestLogId).toBe(41);
|
|
274
275
|
});
|
|
275
276
|
|
|
276
277
|
it("tokenName 을 활성 토큰 id 로 해석해 지정 요청으로 전달한다", async () => {
|
|
@@ -459,7 +460,7 @@ describe("QgridFrame.query request logging", () => {
|
|
|
459
460
|
afterQueryMock.mockRejectedValueOnce(new Error("request log unavailable"));
|
|
460
461
|
const args = { prompt: "hi", model: "openai/gpt-5-codex" };
|
|
461
462
|
|
|
462
|
-
await expect(QgridFrame.query(args)).resolves.
|
|
463
|
+
await expect(QgridFrame.query(args)).resolves.toEqual({ ...output, requestLogId: 41 });
|
|
463
464
|
|
|
464
465
|
expect(finishRunWithErrorMock).toHaveBeenCalledWith(41, "request log unavailable", args);
|
|
465
466
|
});
|
|
@@ -1065,7 +1066,7 @@ describe("QgridFrame.queryStream request logging", () => {
|
|
|
1065
1066
|
expect(order).toEqual(["before", "dispatch", "after"]);
|
|
1066
1067
|
expect(sse.publish).toHaveBeenCalledWith(
|
|
1067
1068
|
"done",
|
|
1068
|
-
expect.objectContaining({ runContext: streamOutput().runContext }),
|
|
1069
|
+
expect.objectContaining({ requestLogId: 52, runContext: streamOutput().runContext }),
|
|
1069
1070
|
);
|
|
1070
1071
|
});
|
|
1071
1072
|
|
|
@@ -281,7 +281,7 @@ class QgridFrameClass extends BaseFrameClass {
|
|
|
281
281
|
lifecycle.runContext || threadCoord
|
|
282
282
|
? { ...lifecycle.runContext, ...(threadCoord ? { threadCoord } : {}) }
|
|
283
283
|
: undefined;
|
|
284
|
-
return { ...result, runContext };
|
|
284
|
+
return { ...result, requestLogId, runContext };
|
|
285
285
|
} catch (e) {
|
|
286
286
|
logger.error(`query afterQuery failed: ${(e as Error).message}`);
|
|
287
287
|
if (disconnect.signal.aborted) {
|
|
@@ -290,7 +290,7 @@ class QgridFrameClass extends BaseFrameClass {
|
|
|
290
290
|
await finishRunWithError(requestLogId, (e as Error).message, resolvedArgs);
|
|
291
291
|
}
|
|
292
292
|
// provider 응답은 성공했으므로 로깅 장애가 생성 결과를 덮어쓰지 않는다.
|
|
293
|
-
return result;
|
|
293
|
+
return { ...result, requestLogId };
|
|
294
294
|
}
|
|
295
295
|
} finally {
|
|
296
296
|
disconnect.dispose();
|
|
@@ -407,7 +407,13 @@ class QgridFrameClass extends BaseFrameClass {
|
|
|
407
407
|
}
|
|
408
408
|
}
|
|
409
409
|
}
|
|
410
|
-
if (!clientClosed && !sse.closed)
|
|
410
|
+
if (!clientClosed && !sse.closed) {
|
|
411
|
+
sse.publish("done", {
|
|
412
|
+
...streamResult,
|
|
413
|
+
...(runInfo ? { requestLogId: runInfo.requestLogId } : {}),
|
|
414
|
+
runContext,
|
|
415
|
+
});
|
|
416
|
+
}
|
|
411
417
|
} else if (streamError) {
|
|
412
418
|
if (runInfo) await finishRunWithError(runInfo.requestLogId, streamError.message, args);
|
|
413
419
|
if (!clientClosed && !sse.closed) sse.publish("error", { message: streamError.message });
|
|
@@ -187,6 +187,7 @@ export const CostSource = z.enum(["provider", "pricing_table", "mixed"]);
|
|
|
187
187
|
export type CostSource = z.infer<typeof CostSource>;
|
|
188
188
|
|
|
189
189
|
export const QueryOutput = z.object({
|
|
190
|
+
requestLogId: z.number().optional(),
|
|
190
191
|
text: z.string(),
|
|
191
192
|
content: z.array(QgridContent),
|
|
192
193
|
finishReason: FinishReason,
|
|
@@ -221,6 +222,7 @@ export const StreamEvents = z.object({
|
|
|
221
222
|
input: z.string(),
|
|
222
223
|
}),
|
|
223
224
|
done: z.object({
|
|
225
|
+
requestLogId: z.number().optional(),
|
|
224
226
|
text: z.string(),
|
|
225
227
|
model: z.string().optional(),
|
|
226
228
|
requestedModel: z.string().optional(),
|
|
@@ -23,6 +23,7 @@ describe("resolveOpenAIEffort", () => {
|
|
|
23
23
|
expect(resolveOpenAIEffort("gpt-5.6-terra", "max")).toBe("max");
|
|
24
24
|
expect(resolveOpenAIEffort("gpt-5.6-terra", "ultra")).toBe("ultra");
|
|
25
25
|
expect(resolveOpenAIEffort("gpt-5.6-luna", "max")).toBe("max");
|
|
26
|
+
expect(resolveOpenAIEffort("gpt-6.1-sol", "ultra")).toBe("ultra");
|
|
26
27
|
expect(resolveOpenAIEffort("gpt-6-sol", "ultra")).toBe("ultra");
|
|
27
28
|
expect(resolveOpenAIEffort("gpt-6-luna", "max")).toBe("max");
|
|
28
29
|
});
|
|
@@ -13,6 +13,7 @@ describe("calculateCostUsd", () => {
|
|
|
13
13
|
});
|
|
14
14
|
it.each([
|
|
15
15
|
["gpt-6-astra", 10, 50, 1, 12.5],
|
|
16
|
+
["gpt-6.1-sol", 2, 10, 0.1, 2.5],
|
|
16
17
|
["gpt-6-sol", 2, 10, 0.2, 2.5],
|
|
17
18
|
["gpt-6-luna", 0.1, 0.5, 0.01, 0.125],
|
|
18
19
|
["gpt-5.6-sol", 4, 20, 0.4, 5],
|
|
@@ -97,6 +98,7 @@ describe("calculateCostUsd", () => {
|
|
|
97
98
|
|
|
98
99
|
it.each([
|
|
99
100
|
["gpt-6-astra", 10, 50, 1, 12.5, 5.6125],
|
|
101
|
+
["gpt-6.1-sol", 2, 10, 0.1, 2.5, 1.1175],
|
|
100
102
|
["gpt-6-sol", 2, 10, 0.2, 2.5, 1.1225],
|
|
101
103
|
["gpt-6-luna", 0.1, 0.5, 0.01, 0.125, 0.056125],
|
|
102
104
|
["gpt-5.6-sol", 4, 20, 0.4, 5, 2.245],
|
|
@@ -125,6 +127,7 @@ describe("calculateCostUsd", () => {
|
|
|
125
127
|
|
|
126
128
|
it.each([
|
|
127
129
|
["gpt-6-astra", 2.475],
|
|
130
|
+
["gpt-6.1-sol", 0.455],
|
|
128
131
|
["gpt-6-sol", 0.495],
|
|
129
132
|
["gpt-6-luna", 0.02475],
|
|
130
133
|
["gpt-5.6-sol", 0.99],
|
|
@@ -142,6 +145,7 @@ describe("calculateCostUsd", () => {
|
|
|
142
145
|
|
|
143
146
|
it.each([
|
|
144
147
|
["gpt-6-astra", 2.725],
|
|
148
|
+
["gpt-6.1-sol", 0.505],
|
|
145
149
|
["gpt-6-sol", 0.545],
|
|
146
150
|
["gpt-6-luna", 0.02725],
|
|
147
151
|
["gpt-5.6-sol", 1.09],
|
|
@@ -65,6 +65,18 @@ const OPENAI_COSTS: Record<string, OpenAIModelSpec> = {
|
|
|
65
65
|
cacheCreationInputTokens: 12.5,
|
|
66
66
|
longContext: LONG_CONTEXT_272K,
|
|
67
67
|
},
|
|
68
|
+
// GPT-6.1 Sol (2026-09-29 DevDay 출시): Standard API pricing verified 2026-09-30. GPT-6 Sol 과 같고 cached input 만 절반.
|
|
69
|
+
// Codex 카탈로그(2026-09-30)는 ultra 까지 허용하고 기본 effort 는 low 다(GPT-6 Sol 은 medium).
|
|
70
|
+
// qgrid 의 요청 형태 + codex_cli_rs/0.147.0 헤더로 2026-09-30 구독 경로 라이브 생성 성공.
|
|
71
|
+
// @see https://developers.openai.com/api/docs/models/gpt-6.1-sol
|
|
72
|
+
"gpt-6.1-sol": {
|
|
73
|
+
maxEffort: "ultra",
|
|
74
|
+
inputTokens: 2,
|
|
75
|
+
outputTokens: 10,
|
|
76
|
+
cachedInputTokens: 0.1,
|
|
77
|
+
cacheCreationInputTokens: 2.5,
|
|
78
|
+
longContext: LONG_CONTEXT_272K,
|
|
79
|
+
},
|
|
68
80
|
// GPT-6 Sol, Luna (2026-09-22 출시): Standard API pricing verified 2026-09-23. GPT-5.6 Sol/Luna 의 절반 단가.
|
|
69
81
|
// Codex 카탈로그(2026-09-23)는 Sol 에 ultra, Luna 에 max 까지 허용하고 기본 effort 는 둘 다 medium 이다.
|
|
70
82
|
// @see https://developers.openai.com/api/docs/models/gpt-6-sol
|
|
@@ -698,6 +698,7 @@ describe("effort 어휘 해석 (Codex 카탈로그 기준)", () => {
|
|
|
698
698
|
|
|
699
699
|
it("모델이 지원하는 값은 그대로 보내고, 상한 초과·공개 API 어휘는 reasoning 에서 빼 백엔드 기본값을 쓴다", async () => {
|
|
700
700
|
await expect(mappedEffortFor("gpt-6-astra", "ultra")).resolves.toBe("ultra");
|
|
701
|
+
await expect(mappedEffortFor("gpt-6.1-sol", "ultra")).resolves.toBe("ultra");
|
|
701
702
|
await expect(mappedEffortFor("gpt-6-sol", "ultra")).resolves.toBe("ultra");
|
|
702
703
|
await expect(mappedEffortFor("gpt-6-luna", "max")).resolves.toBe("max");
|
|
703
704
|
await expect(mappedEffortFor("gpt-6-luna", "ultra")).resolves.toBeUndefined();
|