@cartanova/qgrid-cli 2.3.5 → 2.3.6
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/oauth.js +15 -12
- package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +2 -1
- package/bundle/dist/application/qgrid/qgrid.dispatcher.js +2 -1
- package/bundle/dist/application/qgrid/qgrid.frame.js +23 -10
- package/bundle/dist/application/qgrid/qgrid.types.js +8 -2
- package/bundle/dist/application/qgrid/token-subscriber.js +16 -8
- package/bundle/dist/application/qgrid/token-trigger-setup.js +3 -2
- package/bundle/dist/application/request-log/request-log.model.js +12 -7
- package/bundle/dist/application/sonamu.generated.js +11 -3
- package/bundle/dist/application/sonamu.generated.sso.js +7 -2
- package/bundle/dist/application/token/token.model.js +10 -2
- package/bundle/dist/application/token/token.types.js +5 -3
- package/bundle/dist/i18n/sd.generated.js +4 -1
- package/bundle/dist/migrations/20260630223950_alter_tokens_add1_alter1.js +16 -0
- package/bundle/dist/migrations/20260701105327_alter_request_logs_add1_alter1.js +16 -0
- package/bundle/dist/migrations/20260701105328_alter_request_log_steps_add1_alter1.js +16 -0
- package/bundle/dist/sonamu.config.js +13 -6
- package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +99 -12
- package/bundle/dist/utils/providers/anthropic/anthropic-quota.js +31 -0
- package/bundle/dist/utils/providers/anthropic/claude-session.js +8 -3
- package/bundle/dist/utils/providers/common/ttft.js +25 -0
- package/bundle/dist/utils/providers/openai/codex-worker.js +35 -7
- package/bundle/dist/utils/providers/openai/openai-dispatcher.js +237 -39
- package/bundle/dist/utils/providers/openai/openai-quota.js +30 -0
- package/bundle/src/application/qgrid/oauth.ts +17 -7
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +96 -0
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +1 -0
- package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +16 -0
- package/bundle/src/application/qgrid/qgrid.dispatcher.ts +1 -0
- package/bundle/src/application/qgrid/qgrid.frame.test.ts +128 -0
- package/bundle/src/application/qgrid/qgrid.frame.ts +41 -20
- package/bundle/src/application/qgrid/qgrid.types.ts +6 -0
- package/bundle/src/application/qgrid/token-subscriber.test.ts +89 -0
- package/bundle/src/application/qgrid/token-subscriber.ts +40 -11
- package/bundle/src/application/qgrid/token-trigger-setup.ts +2 -1
- package/bundle/src/application/qgrid/tool-emulation.test.ts +7 -3
- package/bundle/src/application/request-log/request-log.entity.json +3 -0
- package/bundle/src/application/request-log/request-log.model.test.ts +92 -0
- package/bundle/src/application/request-log/request-log.model.ts +20 -6
- package/bundle/src/application/request-log-step/request-log-step.entity.json +3 -0
- package/bundle/src/application/sonamu.generated.http +7 -2
- package/bundle/src/application/sonamu.generated.sso.ts +5 -0
- package/bundle/src/application/sonamu.generated.ts +11 -1
- package/bundle/src/application/token/token.entity.json +8 -2
- package/bundle/src/application/token/token.model.test.ts +69 -0
- package/bundle/src/application/token/token.model.ts +8 -1
- package/bundle/src/application/token/token.types.test.ts +34 -0
- package/bundle/src/application/token/token.types.ts +5 -0
- package/bundle/src/i18n/sd.generated.ts +3 -0
- package/bundle/src/migrations/20260630223950_alter_tokens_add1_alter1.ts +15 -0
- package/bundle/src/migrations/20260701105327_alter_request_logs_add1_alter1.ts +15 -0
- package/bundle/src/migrations/20260701105328_alter_request_log_steps_add1_alter1.ts +15 -0
- package/bundle/src/sonamu.config.ts +8 -1
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.test.ts +183 -15
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +142 -12
- package/bundle/src/utils/providers/anthropic/anthropic-quota.test.ts +89 -0
- package/bundle/src/utils/providers/anthropic/anthropic-quota.ts +27 -0
- package/bundle/src/utils/providers/anthropic/claude-session.ts +7 -2
- package/bundle/src/utils/providers/common/provider-dispatcher.ts +1 -0
- package/bundle/src/utils/providers/common/ttft.test.ts +37 -0
- package/bundle/src/utils/providers/common/ttft.ts +26 -0
- package/bundle/src/utils/providers/openai/codex-worker.test.ts +148 -0
- package/bundle/src/utils/providers/openai/codex-worker.ts +50 -8
- package/bundle/src/utils/providers/openai/openai-dispatcher.test.ts +378 -6
- package/bundle/src/utils/providers/openai/openai-dispatcher.ts +332 -37
- package/bundle/src/utils/providers/openai/openai-quota.test.ts +85 -0
- package/bundle/src/utils/providers/openai/openai-quota.ts +46 -0
- package/bundle/web-dist/client/assets/index-5WdFEqZT.css +1 -0
- package/bundle/web-dist/client/assets/{index-DeThumA3.js → index-jnUY7nJ-.js} +3 -3
- package/bundle/web-dist/client/assets/logs-B0pWpDrg.js +1 -0
- package/bundle/web-dist/client/assets/routes-7XhVuG7o.js +5 -0
- package/bundle/web-dist/client/assets/{sd.generated-7jzAQL2_.js → sd.generated-DXhjjL2f.js} +1 -1
- package/bundle/web-dist/client/assets/{services.generated-Bx1Eh7ot.js → services.generated-B7u0U1wC.js} +1 -1
- package/bundle/web-dist/client/assets/{show-C6OofoAL.js → show-CcjZ9nr7.js} +3 -3
- package/bundle/web-dist/client/assets/tokens-DlwAm0v4.js +1 -0
- package/bundle/web-dist/client/index.html +3 -3
- package/bundle/web-dist/server/assets/{lazyRouteComponent-BEaI4mOq.js → lazyRouteComponent-B0LkbiYf.js} +1 -2
- package/bundle/web-dist/server/assets/{logs-CHM0fhfO.js → logs-dLx6gMXT.js} +17 -5
- package/bundle/web-dist/server/assets/{routes-C9xFMJ_r.js → routes-DD3Hb9xO.js} +201 -13
- package/bundle/web-dist/server/assets/{sd.generated-BeUHLWKH.js → sd.generated-DdfpD_iN.js} +131 -1
- package/bundle/web-dist/server/assets/{services.generated-C39hdSv0.js → services.generated-D3ZCvIkt.js} +5 -4
- package/bundle/web-dist/server/assets/{show-BZWqH09U.js → show-BQjeyv6A.js} +76 -25
- package/bundle/web-dist/server/assets/{tokens-IPwv3pNB.js → tokens-CSOsBpP7.js} +4 -3
- package/bundle/web-dist/server/entry-server.generated.js +6 -7
- package/dist/cli.js +67 -15
- package/package.json +1 -1
- package/bundle/web-dist/client/assets/index-B5DSo5uH.css +0 -1
- package/bundle/web-dist/client/assets/logs-CtmOVH58.js +0 -1
- package/bundle/web-dist/client/assets/routes-Cfoe9J0I.js +0 -5
- package/bundle/web-dist/client/assets/tokens-BAZq8sTo.js +0 -1
- package/bundle/web-dist/server/assets/shim-B9ZrFt3Z.js +0 -129
- /package/bundle/web-dist/server/assets/{cost-DzjfVtUr.js → cost-CSH_t17I.js} +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as RequestLogService, r as RequestLogStepService } from "./services.generated-
|
|
3
|
-
import { a as Link } from "./lazyRouteComponent-
|
|
1
|
+
import { J as __exportAll, X as __toESM, _ as require_react, g as require_jsx_runtime, q as __commonJSMin } from "./sd.generated-DdfpD_iN.js";
|
|
2
|
+
import { n as RequestLogService, r as RequestLogStepService } from "./services.generated-D3ZCvIkt.js";
|
|
3
|
+
import { a as Link } from "./lazyRouteComponent-B0LkbiYf.js";
|
|
4
4
|
import { t as Route } from "../entry-server.generated.js";
|
|
5
|
-
import { n as formatMicroUsd, t as cacheHitRate } from "./cost-
|
|
5
|
+
import { n as formatMicroUsd, t as cacheHitRate } from "./cost-CSH_t17I.js";
|
|
6
6
|
import minpath from "node:path";
|
|
7
7
|
import minproc from "node:process";
|
|
8
8
|
import { fileURLToPath as urlToPath } from "node:url";
|
|
@@ -25088,11 +25088,15 @@ function RequestShowPage() {
|
|
|
25088
25088
|
function formatNum(n) {
|
|
25089
25089
|
return n.toLocaleString();
|
|
25090
25090
|
}
|
|
25091
|
+
var TOKENS_PER_SEC_PROVIDERS = /* @__PURE__ */ new Set();
|
|
25091
25092
|
function tryParseJson(text) {
|
|
25092
25093
|
try {
|
|
25093
|
-
return
|
|
25094
|
+
return {
|
|
25095
|
+
ok: true,
|
|
25096
|
+
value: JSON.parse(text)
|
|
25097
|
+
};
|
|
25094
25098
|
} catch {
|
|
25095
|
-
return
|
|
25099
|
+
return { ok: false };
|
|
25096
25100
|
}
|
|
25097
25101
|
}
|
|
25098
25102
|
function safeParseJson(text) {
|
|
@@ -25106,7 +25110,7 @@ function safeParseJson(text) {
|
|
|
25106
25110
|
function CopyButton({ text }) {
|
|
25107
25111
|
const [copied, setCopied] = (0, import_react.useState)(false);
|
|
25108
25112
|
(0, import_react.useEffect)(() => {
|
|
25109
|
-
if (!copied) return;
|
|
25113
|
+
if (!copied) return void 0;
|
|
25110
25114
|
const id = setTimeout(() => setCopied(false), 1500);
|
|
25111
25115
|
return () => clearTimeout(id);
|
|
25112
25116
|
}, [copied]);
|
|
@@ -25124,7 +25128,7 @@ function CopyButton({ text }) {
|
|
|
25124
25128
|
function FormattedContent({ text, markdown }) {
|
|
25125
25129
|
const parsed = tryParseJson(text);
|
|
25126
25130
|
const [mode, setMode] = (0, import_react.useState)("pretty");
|
|
25127
|
-
if (parsed
|
|
25131
|
+
if (!parsed.ok) {
|
|
25128
25132
|
if (markdown) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
25129
25133
|
className: "prose prose-sm prose-qgrid max-w-none",
|
|
25130
25134
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Markdown, {
|
|
@@ -25151,14 +25155,14 @@ function FormattedContent({ text, markdown }) {
|
|
|
25151
25155
|
children: "Pretty"
|
|
25152
25156
|
})]
|
|
25153
25157
|
}), mode === "pretty" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(JsonView, {
|
|
25154
|
-
value: parsed,
|
|
25158
|
+
value: parsed.value,
|
|
25155
25159
|
style: lightTheme,
|
|
25156
25160
|
displayDataTypes: false,
|
|
25157
25161
|
enableClipboard: true,
|
|
25158
25162
|
collapsed: false
|
|
25159
25163
|
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", {
|
|
25160
25164
|
className: "text-sm text-sand-800 whitespace-pre-wrap wrap-break-word font-mono leading-relaxed",
|
|
25161
|
-
children: JSON.stringify(parsed, null, 2)
|
|
25165
|
+
children: JSON.stringify(parsed.value, null, 2)
|
|
25162
25166
|
})] });
|
|
25163
25167
|
}
|
|
25164
25168
|
function Section({ title, defaultOpen = true, children }) {
|
|
@@ -25239,15 +25243,24 @@ function HeaderBar({ data }) {
|
|
|
25239
25243
|
});
|
|
25240
25244
|
}
|
|
25241
25245
|
function MetricsPanel({ data, toolCallCount }) {
|
|
25246
|
+
const tokensPerSecEnabled = isTokensPerSecEnabled(data);
|
|
25242
25247
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
25243
25248
|
className: "panel overflow-hidden px-5 py-3 space-y-3",
|
|
25244
25249
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
25245
|
-
className: "grid grid-cols-
|
|
25250
|
+
className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-x-6 gap-y-3",
|
|
25246
25251
|
children: [
|
|
25247
25252
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Metric, {
|
|
25248
25253
|
label: "Duration",
|
|
25249
25254
|
value: `${(data.duration_ms / 1e3).toFixed(1)}s`
|
|
25250
25255
|
}),
|
|
25256
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Metric, {
|
|
25257
|
+
label: "TTFT",
|
|
25258
|
+
value: formatDurationMs(data.ttft_ms)
|
|
25259
|
+
}),
|
|
25260
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Metric, {
|
|
25261
|
+
label: "Tokens/sec",
|
|
25262
|
+
value: formatTokensPerSec(data.output_tokens, data.duration_ms, data.ttft_ms, tokensPerSecEnabled)
|
|
25263
|
+
}),
|
|
25251
25264
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Metric, {
|
|
25252
25265
|
label: "Cost",
|
|
25253
25266
|
value: data.cost_usd !== null ? formatMicroUsd(data.cost_usd) : "—"
|
|
@@ -25255,14 +25268,10 @@ function MetricsPanel({ data, toolCallCount }) {
|
|
|
25255
25268
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Metric, {
|
|
25256
25269
|
label: "Tool Calls",
|
|
25257
25270
|
value: `${toolCallCount}회`
|
|
25258
|
-
}),
|
|
25259
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Metric, {
|
|
25260
|
-
label: "Cache Hit",
|
|
25261
|
-
value: cacheHitRate(data)
|
|
25262
25271
|
})
|
|
25263
25272
|
]
|
|
25264
25273
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
25265
|
-
className: "border-t border-sand-100/60 pt-3 grid grid-cols-
|
|
25274
|
+
className: "border-t border-sand-100/60 pt-3 grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-x-6 gap-y-3",
|
|
25266
25275
|
children: [
|
|
25267
25276
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Metric, {
|
|
25268
25277
|
label: "Input",
|
|
@@ -25279,15 +25288,41 @@ function MetricsPanel({ data, toolCallCount }) {
|
|
|
25279
25288
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Metric, {
|
|
25280
25289
|
label: "Cache Write",
|
|
25281
25290
|
value: formatNum(data.cache_creation_tokens)
|
|
25291
|
+
}),
|
|
25292
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Metric, {
|
|
25293
|
+
label: "Cache Hit",
|
|
25294
|
+
value: cacheHitRate(data)
|
|
25282
25295
|
})
|
|
25283
25296
|
]
|
|
25284
25297
|
})]
|
|
25285
25298
|
});
|
|
25286
25299
|
}
|
|
25287
25300
|
function formatDurationMs(ms) {
|
|
25288
|
-
if (ms
|
|
25301
|
+
if (ms === null || ms === void 0) return "—";
|
|
25289
25302
|
return ms >= 1e3 ? `${(ms / 1e3).toFixed(1)}s` : `${ms}ms`;
|
|
25290
25303
|
}
|
|
25304
|
+
function detectTokenRateProvider(source) {
|
|
25305
|
+
const modelName = source.model_name?.trim().toLowerCase();
|
|
25306
|
+
if (modelName) {
|
|
25307
|
+
const canonical = modelName.includes("/") ? modelName.split("/").pop() : modelName;
|
|
25308
|
+
if (canonical.startsWith("claude-")) return "anthropic";
|
|
25309
|
+
if (/^(gpt-|codex-|o\d)/.test(canonical)) return "openai";
|
|
25310
|
+
}
|
|
25311
|
+
const tokenName = source.token_name?.trim().toLowerCase();
|
|
25312
|
+
if (tokenName?.startsWith("anthropic/")) return "anthropic";
|
|
25313
|
+
if (tokenName?.startsWith("openai/")) return "openai";
|
|
25314
|
+
return null;
|
|
25315
|
+
}
|
|
25316
|
+
function isTokensPerSecEnabled(source) {
|
|
25317
|
+
const provider = detectTokenRateProvider(source);
|
|
25318
|
+
return provider !== null && TOKENS_PER_SEC_PROVIDERS.has(provider);
|
|
25319
|
+
}
|
|
25320
|
+
function formatTokensPerSec(outputTokens, durationMs, ttftMs, enabled) {
|
|
25321
|
+
if (!enabled || outputTokens === null || outputTokens === void 0 || durationMs === null || durationMs === void 0 || ttftMs === null || ttftMs === void 0) return "—";
|
|
25322
|
+
const generationMs = durationMs - ttftMs;
|
|
25323
|
+
if (outputTokens <= 0 || generationMs <= 0) return "—";
|
|
25324
|
+
return `${Math.round(outputTokens / (generationMs / 1e3)).toLocaleString()} tok/s`;
|
|
25325
|
+
}
|
|
25291
25326
|
function CompactMetric({ label, value }) {
|
|
25292
25327
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
25293
25328
|
className: "text-[10px] uppercase tracking-wider text-sand-400 font-medium",
|
|
@@ -25387,9 +25422,9 @@ function ReasoningBlock({ stepId }) {
|
|
|
25387
25422
|
})]
|
|
25388
25423
|
});
|
|
25389
25424
|
}
|
|
25390
|
-
function StepTreeItem({ entry }) {
|
|
25425
|
+
function StepTreeItem({ entry, tokensPerSecEnabled }) {
|
|
25391
25426
|
const generate = entry.generate;
|
|
25392
|
-
const hasReasoning = generate
|
|
25427
|
+
const hasReasoning = generate !== null && generate.reasoningTokens !== null && generate.reasoningTokens !== void 0 && generate.reasoningTokens > 0;
|
|
25393
25428
|
const errorCount = entry.toolCalls.filter((toolCall) => toolCall.error).length;
|
|
25394
25429
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", {
|
|
25395
25430
|
open: true,
|
|
@@ -25428,12 +25463,20 @@ function StepTreeItem({ entry }) {
|
|
|
25428
25463
|
children: [generate && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
25429
25464
|
className: "rounded-md border border-sand-100 bg-sand-50/70 p-3",
|
|
25430
25465
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
25431
|
-
className: "grid grid-cols-
|
|
25466
|
+
className: "grid grid-cols-2 md:grid-cols-4 xl:grid-cols-8 gap-3",
|
|
25432
25467
|
children: [
|
|
25433
25468
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CompactMetric, {
|
|
25434
25469
|
label: "Duration",
|
|
25435
25470
|
value: formatDurationMs(generate.durationMs)
|
|
25436
25471
|
}),
|
|
25472
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CompactMetric, {
|
|
25473
|
+
label: "TTFT",
|
|
25474
|
+
value: formatDurationMs(generate.ttftMs)
|
|
25475
|
+
}),
|
|
25476
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CompactMetric, {
|
|
25477
|
+
label: "Tokens/sec",
|
|
25478
|
+
value: formatTokensPerSec(generate.outputTokens, generate.durationMs, generate.ttftMs, tokensPerSecEnabled)
|
|
25479
|
+
}),
|
|
25437
25480
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CompactMetric, {
|
|
25438
25481
|
label: "Input",
|
|
25439
25482
|
value: formatNum(generate.inputTokens ?? 0)
|
|
@@ -25452,7 +25495,7 @@ function StepTreeItem({ entry }) {
|
|
|
25452
25495
|
}),
|
|
25453
25496
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CompactMetric, {
|
|
25454
25497
|
label: "Reasoning",
|
|
25455
|
-
value: generate.reasoningTokens
|
|
25498
|
+
value: generate.reasoningTokens !== null && generate.reasoningTokens !== void 0 ? formatNum(generate.reasoningTokens) : "—"
|
|
25456
25499
|
})
|
|
25457
25500
|
]
|
|
25458
25501
|
}), hasReasoning && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReasoningBlock, { stepId: generate.id })]
|
|
@@ -25463,14 +25506,17 @@ function StepTreeItem({ entry }) {
|
|
|
25463
25506
|
})]
|
|
25464
25507
|
});
|
|
25465
25508
|
}
|
|
25466
|
-
function StepTreeSection({ steps }) {
|
|
25509
|
+
function StepTreeSection({ steps, tokensPerSecEnabled }) {
|
|
25467
25510
|
const toolCallCount = steps.reduce((sum, step) => sum + step.toolCalls.length, 0);
|
|
25468
25511
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Section, {
|
|
25469
25512
|
title: `Steps (${steps.length} steps · ${toolCallCount} tool calls)`,
|
|
25470
25513
|
defaultOpen: true,
|
|
25471
25514
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
25472
25515
|
className: "space-y-1",
|
|
25473
|
-
children: steps.map((step) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StepTreeItem, {
|
|
25516
|
+
children: steps.map((step) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StepTreeItem, {
|
|
25517
|
+
entry: step,
|
|
25518
|
+
tokensPerSecEnabled
|
|
25519
|
+
}, step.stepIndex))
|
|
25474
25520
|
})
|
|
25475
25521
|
});
|
|
25476
25522
|
}
|
|
@@ -25498,6 +25544,7 @@ function buildStepTree(steps) {
|
|
|
25498
25544
|
cacheReadTokens: step.cache_read_tokens,
|
|
25499
25545
|
cacheCreationTokens: step.cache_creation_tokens,
|
|
25500
25546
|
durationMs: step.duration_ms,
|
|
25547
|
+
ttftMs: step.ttft_ms,
|
|
25501
25548
|
finishReason: step.finish_reason,
|
|
25502
25549
|
reasoningTokens: step.reasoning_tokens
|
|
25503
25550
|
};
|
|
@@ -25549,7 +25596,7 @@ function HistorySection({ history }) {
|
|
|
25549
25596
|
className: "text-[10px] uppercase tracking-wider text-sand-500 font-medium mb-1",
|
|
25550
25597
|
children: historyItemLabel(item)
|
|
25551
25598
|
}),
|
|
25552
|
-
item.content
|
|
25599
|
+
item.content !== null && item.content !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", {
|
|
25553
25600
|
className: "text-[12px] text-sand-700 whitespace-pre-wrap wrap-break-word font-mono leading-relaxed max-h-40 overflow-auto",
|
|
25554
25601
|
children: extractText(item.content)
|
|
25555
25602
|
}),
|
|
@@ -25596,6 +25643,7 @@ function RequestDetail({ id }) {
|
|
|
25596
25643
|
const stepTree = buildStepTree(stepsData?.rows ?? []);
|
|
25597
25644
|
const toolCalls = stepTree.flatMap((step) => step.toolCalls);
|
|
25598
25645
|
const hasSteps = stepTree.length > 0;
|
|
25646
|
+
const tokensPerSecEnabled = isTokensPerSecEnabled(data);
|
|
25599
25647
|
const history = data.history ?? null;
|
|
25600
25648
|
const hasHistory = history !== null && history.length > 0;
|
|
25601
25649
|
const promptSections = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
@@ -25638,7 +25686,10 @@ function RequestDetail({ id }) {
|
|
|
25638
25686
|
children: promptSections
|
|
25639
25687
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
25640
25688
|
className: "flex-1 min-w-0 space-y-4",
|
|
25641
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StepTreeSection, {
|
|
25689
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StepTreeSection, {
|
|
25690
|
+
steps: stepTree,
|
|
25691
|
+
tokensPerSecEnabled
|
|
25692
|
+
})
|
|
25642
25693
|
})]
|
|
25643
25694
|
}) : promptSections,
|
|
25644
25695
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Section, {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { i as TokenService, t as QgridService } from "./services.generated-
|
|
1
|
+
import { X as __toESM, _ as require_react, g as require_jsx_runtime, h as useQueryClient } from "./sd.generated-DdfpD_iN.js";
|
|
2
|
+
import { i as TokenService, t as QgridService } from "./services.generated-D3ZCvIkt.js";
|
|
3
3
|
import { i as lucideKeyRound, r as Q } from "../entry-server.generated.js";
|
|
4
4
|
//#region ~icons/lucide/plus.jsx
|
|
5
5
|
var import_react = /* @__PURE__ */ __toESM(require_react());
|
|
@@ -237,7 +237,8 @@ function TokenTable({ data, isLoading }) {
|
|
|
237
237
|
if (!editTarget) return;
|
|
238
238
|
await updateMutation.mutateAsync({
|
|
239
239
|
id: editTarget.id,
|
|
240
|
-
name: editName.trim()
|
|
240
|
+
name: editName.trim(),
|
|
241
|
+
quotaThreshold: editTarget.quota_threshold
|
|
241
242
|
});
|
|
242
243
|
await invalidate();
|
|
243
244
|
setEditTarget(null);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { A as
|
|
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-
|
|
3
|
-
import { t as require_shim } from "./assets/shim-B9ZrFt3Z.js";
|
|
1
|
+
import { A as hashKey, C as Query, E as notifyManager, F as noop$1, G as focusManager, H as skipToken, I as partialMatchKey, K as Subscribable, N as matchMutation, P as matchQuery, S as infiniteQueryBehavior, T as onlineManager, X as __toESM, Y as __require, _ as require_react, c as number, f as require_react_dom, g as require_jsx_runtime, j as hashQueryKeyByOptions, k as functionalUpdate, l as object, m as QueryClientProvider, n as SUPPORTED_LOCALES, p as require_shim, q as __commonJSMin, r as setLocale, t as SD, u as string, v as Mutation, z as resolveStaleTime } from "./assets/sd.generated-DdfpD_iN.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-B0LkbiYf.js";
|
|
4
3
|
//#region ../../node_modules/.pnpm/@tanstack+query-core@5.95.2/node_modules/@tanstack/query-core/build/modern/hydration.js
|
|
5
4
|
function defaultTransformerFn(data) {
|
|
6
5
|
return data;
|
|
@@ -44559,11 +44558,11 @@ function RootComponent() {
|
|
|
44559
44558
|
}
|
|
44560
44559
|
//#endregion
|
|
44561
44560
|
//#region src/routes/tokens.tsx
|
|
44562
|
-
var $$splitComponentImporter$3 = () => import("./assets/tokens-
|
|
44561
|
+
var $$splitComponentImporter$3 = () => import("./assets/tokens-CSOsBpP7.js");
|
|
44563
44562
|
var Route$3 = createFileRoute("/tokens")({ component: lazyRouteComponent($$splitComponentImporter$3, "component") });
|
|
44564
44563
|
//#endregion
|
|
44565
44564
|
//#region src/routes/logs.tsx
|
|
44566
|
-
var $$splitComponentImporter$2 = () => import("./assets/logs-
|
|
44565
|
+
var $$splitComponentImporter$2 = () => import("./assets/logs-dLx6gMXT.js");
|
|
44567
44566
|
var logsSearchSchema = object({
|
|
44568
44567
|
token: string().optional(),
|
|
44569
44568
|
project: string().optional(),
|
|
@@ -44575,11 +44574,11 @@ var Route$2 = createFileRoute("/logs")({
|
|
|
44575
44574
|
});
|
|
44576
44575
|
//#endregion
|
|
44577
44576
|
//#region src/routes/index.tsx
|
|
44578
|
-
var $$splitComponentImporter$1 = () => import("./assets/routes-
|
|
44577
|
+
var $$splitComponentImporter$1 = () => import("./assets/routes-DD3Hb9xO.js");
|
|
44579
44578
|
var Route$1 = createFileRoute("/")({ component: lazyRouteComponent($$splitComponentImporter$1, "component") });
|
|
44580
44579
|
//#endregion
|
|
44581
44580
|
//#region src/routes/requests/show.tsx
|
|
44582
|
-
var $$splitComponentImporter = () => import("./assets/show-
|
|
44581
|
+
var $$splitComponentImporter = () => import("./assets/show-BQjeyv6A.js");
|
|
44583
44582
|
var showSearchSchema = object({ id: number() });
|
|
44584
44583
|
var Route = createFileRoute("/requests/show")({
|
|
44585
44584
|
validateSearch: showSearchSchema,
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { execSync, spawnSync } from "node:child_process";
|
|
2
|
+
import { execFileSync, execSync, spawnSync } from "node:child_process";
|
|
3
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
@@ -7,12 +7,71 @@ import { Command } from "commander";
|
|
|
7
7
|
//#region src/cli.ts
|
|
8
8
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
9
|
const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
|
|
10
|
-
|
|
10
|
+
const RUNTIME_CLI_DEPENDENCIES = [{
|
|
11
|
+
command: "codex",
|
|
12
|
+
packageName: "@openai/codex",
|
|
13
|
+
label: "Codex CLI",
|
|
14
|
+
missingReason: "OpenAI tokens require codex app-server."
|
|
15
|
+
}, {
|
|
16
|
+
command: "claude",
|
|
17
|
+
packageName: "@anthropic-ai/claude-code",
|
|
18
|
+
label: "Claude Code",
|
|
19
|
+
missingReason: "Anthropic tokens require Claude Code."
|
|
20
|
+
}];
|
|
21
|
+
function commandVersion(command) {
|
|
11
22
|
try {
|
|
12
|
-
|
|
13
|
-
|
|
23
|
+
return execFileSync(command, ["--version"], {
|
|
24
|
+
encoding: "utf-8",
|
|
25
|
+
stdio: "pipe"
|
|
26
|
+
}).trim();
|
|
14
27
|
} catch {
|
|
15
|
-
return
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function packageLatestVersion(packageName) {
|
|
32
|
+
return execFileSync("npm", [
|
|
33
|
+
"view",
|
|
34
|
+
packageName,
|
|
35
|
+
"version"
|
|
36
|
+
], {
|
|
37
|
+
encoding: "utf-8",
|
|
38
|
+
stdio: "pipe"
|
|
39
|
+
}).trim();
|
|
40
|
+
}
|
|
41
|
+
function parseVersion(output) {
|
|
42
|
+
return output?.match(/\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?/)?.[0] ?? null;
|
|
43
|
+
}
|
|
44
|
+
function warnMissingRuntimeCliDependency(dep) {
|
|
45
|
+
console.warn(`Warning: ${dep.command} CLI not found. ${dep.missingReason}`);
|
|
46
|
+
console.warn(`Install: npm i -g ${dep.packageName}`);
|
|
47
|
+
}
|
|
48
|
+
function installRuntimeCliDependency(dep) {
|
|
49
|
+
execFileSync("npm", [
|
|
50
|
+
"i",
|
|
51
|
+
"-g",
|
|
52
|
+
`${dep.packageName}@latest`
|
|
53
|
+
], { stdio: "inherit" });
|
|
54
|
+
}
|
|
55
|
+
function ensureLatestRuntimeCliDependencies() {
|
|
56
|
+
for (const dep of RUNTIME_CLI_DEPENDENCIES) {
|
|
57
|
+
let installedOutput = commandVersion(dep.command);
|
|
58
|
+
try {
|
|
59
|
+
const installed = parseVersion(installedOutput);
|
|
60
|
+
if (!installed) {
|
|
61
|
+
console.log(`Updating ${dep.label}: installing latest`);
|
|
62
|
+
installRuntimeCliDependency(dep);
|
|
63
|
+
installedOutput = commandVersion(dep.command);
|
|
64
|
+
} else {
|
|
65
|
+
const latest = packageLatestVersion(dep.packageName);
|
|
66
|
+
if (installed === latest) continue;
|
|
67
|
+
console.log(`Updating ${dep.label}: ${installed} → ${latest}`);
|
|
68
|
+
installRuntimeCliDependency(dep);
|
|
69
|
+
installedOutput = commandVersion(dep.command);
|
|
70
|
+
}
|
|
71
|
+
} catch (e) {
|
|
72
|
+
console.warn(`Warning: failed to update ${dep.label}: ${e.message}`);
|
|
73
|
+
}
|
|
74
|
+
if (!installedOutput) warnMissingRuntimeCliDependency(dep);
|
|
16
75
|
}
|
|
17
76
|
}
|
|
18
77
|
function normalizePort(port) {
|
|
@@ -25,7 +84,7 @@ function normalizePort(port) {
|
|
|
25
84
|
return value;
|
|
26
85
|
}
|
|
27
86
|
const program = new Command();
|
|
28
|
-
program.name("qgrid").version(pkg.version).description("Qgrid — LLM subscription token proxy server").option("--db <url>", "PostgreSQL connection URL (e.g. postgres://user:pw@host:port/dbname)").option("-p, --port <port>", "server port (default: 44900)").option("--skip-update", "skip
|
|
87
|
+
program.name("qgrid").version(pkg.version).description("Qgrid — LLM subscription token proxy server").option("--db <url>", "PostgreSQL connection URL (e.g. postgres://user:pw@host:port/dbname)").option("-p, --port <port>", "server port (default: 44900)").option("--skip-update", "skip qgrid self-update check").action(async (opts) => {
|
|
29
88
|
const serverPort = normalizePort(opts.port ?? "44900");
|
|
30
89
|
try {
|
|
31
90
|
const pid = execSync(`lsof -ti :${serverPort}`, { encoding: "utf-8" }).trim();
|
|
@@ -36,7 +95,7 @@ program.name("qgrid").version(pkg.version).description("Qgrid — LLM subscripti
|
|
|
36
95
|
}
|
|
37
96
|
} catch {}
|
|
38
97
|
if (!opts.skipUpdate) {
|
|
39
|
-
const latest =
|
|
98
|
+
const latest = packageLatestVersion("@cartanova/qgrid-cli");
|
|
40
99
|
if (latest !== pkg.version) {
|
|
41
100
|
const installCmd = process.env.npm_config_user_agent?.includes("pnpm") || execSync("which qgrid", { encoding: "utf-8" }).includes("pnpm") ? "pnpm add -g @cartanova/qgrid-cli@latest" : "npm i -g @cartanova/qgrid-cli@latest";
|
|
42
101
|
console.log(`Updating qgrid-cli: ${pkg.version} → ${latest}`);
|
|
@@ -46,6 +105,7 @@ program.name("qgrid").version(pkg.version).description("Qgrid — LLM subscripti
|
|
|
46
105
|
process.exit(restarted.status ?? 0);
|
|
47
106
|
}
|
|
48
107
|
}
|
|
108
|
+
ensureLatestRuntimeCliDependencies();
|
|
49
109
|
if (opts.db) {
|
|
50
110
|
const m = opts.db.match(/^postgres(?:ql)?:\/\/([^:]+):(.+)@([^:]+):(\d+)\/(.+)$/);
|
|
51
111
|
if (!m) {
|
|
@@ -60,14 +120,6 @@ program.name("qgrid").version(pkg.version).description("Qgrid — LLM subscripti
|
|
|
60
120
|
process.env.QGRID_DB_NAME = dbName;
|
|
61
121
|
}
|
|
62
122
|
process.env.PORT = serverPort;
|
|
63
|
-
if (!hasCommand("codex")) {
|
|
64
|
-
console.warn("Warning: codex CLI not found. OpenAI tokens require codex app-server.");
|
|
65
|
-
console.warn("Install: npm i -g @openai/codex");
|
|
66
|
-
}
|
|
67
|
-
if (!hasCommand("claude")) {
|
|
68
|
-
console.warn("Warning: claude CLI not found. Anthropic tokens require Claude Code.");
|
|
69
|
-
console.warn("Install: npm i -g @anthropic-ai/claude-code");
|
|
70
|
-
}
|
|
71
123
|
process.env.LR = "remote";
|
|
72
124
|
const bundlePath = join(__dirname, "..", "bundle");
|
|
73
125
|
const serverEntry = join(bundlePath, "dist", "index.js");
|