@dan-ai-studio/dshopencodego 0.1.63 → 0.1.65
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/README.en.md +17 -4
- package/README.md +17 -4
- package/lib/client.js +893 -92
- package/lib/index.js +485 -131
- package/lib/types/adapter.d.ts +7 -0
- package/lib/types/config.d.ts +19 -0
- package/lib/types/network/pinning.d.ts +15 -0
- package/lib/types/request-log/contract.d.ts +23 -0
- package/lib/types/request-log/index.d.ts +10 -0
- package/lib/types/request-log/limits.d.ts +15 -0
- package/lib/types/request-log/service.d.ts +26 -0
- package/lib/types/request-log/store.d.ts +208 -0
- package/package.json +18 -1
package/lib/client.js
CHANGED
|
@@ -55,16 +55,16 @@ function parseGoQuota(value) {
|
|
|
55
55
|
function parseCost(value) {
|
|
56
56
|
if (value === null || typeof value !== "object") throw new Error("invalid model cost");
|
|
57
57
|
const row = value;
|
|
58
|
-
const
|
|
58
|
+
const rate3 = (key) => {
|
|
59
59
|
const entry = row[key];
|
|
60
60
|
if (typeof entry !== "number" || !Number.isFinite(entry) || entry < 0) throw new Error(`invalid model cost "${key}"`);
|
|
61
61
|
return entry;
|
|
62
62
|
};
|
|
63
63
|
return {
|
|
64
|
-
input:
|
|
65
|
-
output:
|
|
66
|
-
...typeof row["cacheRead"] === "number" ? { cacheRead:
|
|
67
|
-
...typeof row["cacheWrite"] === "number" ? { cacheWrite:
|
|
64
|
+
input: rate3("input"),
|
|
65
|
+
output: rate3("output"),
|
|
66
|
+
...typeof row["cacheRead"] === "number" ? { cacheRead: rate3("cacheRead") } : {},
|
|
67
|
+
...typeof row["cacheWrite"] === "number" ? { cacheWrite: rate3("cacheWrite") } : {}
|
|
68
68
|
};
|
|
69
69
|
}
|
|
70
70
|
function parseModalities(value) {
|
|
@@ -115,7 +115,7 @@ function parseCatalogReading(value) {
|
|
|
115
115
|
throw new Error("invalid catalog reading");
|
|
116
116
|
}
|
|
117
117
|
const numbers = counts;
|
|
118
|
-
const
|
|
118
|
+
const count3 = (key) => {
|
|
119
119
|
const entry = numbers[key];
|
|
120
120
|
if (typeof entry !== "number" || !Number.isFinite(entry) || entry < 0) throw new Error(`invalid catalog count "${key}"`);
|
|
121
121
|
return entry;
|
|
@@ -134,11 +134,11 @@ function parseCatalogReading(value) {
|
|
|
134
134
|
fetchedAtMs: row["fetchedAtMs"],
|
|
135
135
|
quotaSource: quotaSource ?? "seed",
|
|
136
136
|
counts: {
|
|
137
|
-
total:
|
|
138
|
-
enabled:
|
|
139
|
-
deprecated:
|
|
140
|
-
unconfigured:
|
|
141
|
-
inferred:
|
|
137
|
+
total: count3("total"),
|
|
138
|
+
enabled: count3("enabled"),
|
|
139
|
+
deprecated: count3("deprecated"),
|
|
140
|
+
unconfigured: count3("unconfigured"),
|
|
141
|
+
inferred: count3("inferred")
|
|
142
142
|
}
|
|
143
143
|
};
|
|
144
144
|
}
|
|
@@ -207,6 +207,115 @@ var networkRemote = {
|
|
|
207
207
|
]
|
|
208
208
|
};
|
|
209
209
|
|
|
210
|
+
// src/request-log/contract.ts
|
|
211
|
+
function count(key, row, optional) {
|
|
212
|
+
const entry = row[key];
|
|
213
|
+
if (entry === void 0) {
|
|
214
|
+
if (optional === true) return void 0;
|
|
215
|
+
throw new Error(`invalid request-log entry "${key}"`);
|
|
216
|
+
}
|
|
217
|
+
if (typeof entry !== "number" || !Number.isFinite(entry) || entry < 0) {
|
|
218
|
+
throw new Error(`invalid request-log entry "${key}"`);
|
|
219
|
+
}
|
|
220
|
+
return entry;
|
|
221
|
+
}
|
|
222
|
+
function text(key, row, optional) {
|
|
223
|
+
const entry = row[key];
|
|
224
|
+
if (entry === void 0) {
|
|
225
|
+
if (optional === true) return void 0;
|
|
226
|
+
throw new Error(`invalid request-log entry "${key}"`);
|
|
227
|
+
}
|
|
228
|
+
if (typeof entry !== "string") throw new Error(`invalid request-log entry "${key}"`);
|
|
229
|
+
return entry;
|
|
230
|
+
}
|
|
231
|
+
function parseEntry(value) {
|
|
232
|
+
if (value === null || typeof value !== "object") throw new Error("invalid request-log entry");
|
|
233
|
+
const row = value;
|
|
234
|
+
const shape = row["shape"];
|
|
235
|
+
const headers = row["headers"];
|
|
236
|
+
return {
|
|
237
|
+
seq: count("seq", row),
|
|
238
|
+
atMs: count("atMs", row),
|
|
239
|
+
model: text("model", row),
|
|
240
|
+
session: text("session", row),
|
|
241
|
+
method: text("method", row),
|
|
242
|
+
url: text("url", row),
|
|
243
|
+
...row["status"] === void 0 ? {} : { status: count("status", row) },
|
|
244
|
+
...row["inputTokens"] === void 0 ? {} : { inputTokens: count("inputTokens", row) },
|
|
245
|
+
...row["outputTokens"] === void 0 ? {} : { outputTokens: count("outputTokens", row) },
|
|
246
|
+
...row["cacheReadTokens"] === void 0 ? {} : { cacheReadTokens: count("cacheReadTokens", row) },
|
|
247
|
+
...row["durationMs"] === void 0 ? {} : { durationMs: count("durationMs", row) },
|
|
248
|
+
...row["firstTokenMs"] === void 0 ? {} : { firstTokenMs: count("firstTokenMs", row) },
|
|
249
|
+
...row["decodeMs"] === void 0 ? {} : { decodeMs: count("decodeMs", row) },
|
|
250
|
+
...row["tps"] === void 0 ? {} : { tps: rate("tps", row) },
|
|
251
|
+
ok: row["ok"] === true,
|
|
252
|
+
...typeof row["code"] === "string" ? { code: row["code"] } : {},
|
|
253
|
+
...typeof row["poolKey"] === "string" ? { poolKey: row["poolKey"] } : {},
|
|
254
|
+
...shape !== null && typeof shape === "object" ? {
|
|
255
|
+
shape: {
|
|
256
|
+
messages: count("messages", shape),
|
|
257
|
+
hasImage: shape["hasImage"] === true,
|
|
258
|
+
tools: count("tools", shape)
|
|
259
|
+
}
|
|
260
|
+
} : {},
|
|
261
|
+
...headers !== null && typeof headers === "object" ? {
|
|
262
|
+
headers: {
|
|
263
|
+
...typeof headers["session"] === "string" ? { session: headers["session"] } : {},
|
|
264
|
+
...typeof headers["userAgent"] === "string" ? { userAgent: headers["userAgent"] } : {}
|
|
265
|
+
}
|
|
266
|
+
} : {}
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
function rate(key, row) {
|
|
270
|
+
const entry = row[key];
|
|
271
|
+
if (typeof entry !== "number" || !Number.isFinite(entry) || entry < 0) {
|
|
272
|
+
throw new Error(`invalid request-log entry "${key}"`);
|
|
273
|
+
}
|
|
274
|
+
return entry;
|
|
275
|
+
}
|
|
276
|
+
function parsePoolEvent(value) {
|
|
277
|
+
if (value === null || typeof value !== "object") throw new Error("invalid request-log pool event");
|
|
278
|
+
const row = value;
|
|
279
|
+
const type = row["type"];
|
|
280
|
+
if (type !== "create" && type !== "close") throw new Error("invalid request-log pool event");
|
|
281
|
+
return { atMs: count("atMs", row), type, key: text("key", row) };
|
|
282
|
+
}
|
|
283
|
+
function parseRequestLogSnapshot(value) {
|
|
284
|
+
if (value === null || typeof value !== "object") throw new Error("invalid request-log snapshot");
|
|
285
|
+
const row = value;
|
|
286
|
+
if (!Array.isArray(row["entries"]) || !Array.isArray(row["poolEvents"])) {
|
|
287
|
+
throw new Error("invalid request-log snapshot");
|
|
288
|
+
}
|
|
289
|
+
return {
|
|
290
|
+
entries: row["entries"].map(parseEntry),
|
|
291
|
+
poolEvents: row["poolEvents"].map(parsePoolEvent),
|
|
292
|
+
totalRecords: count("totalRecords", row),
|
|
293
|
+
droppedRecords: count("droppedRecords", row),
|
|
294
|
+
newConnections: count("newConnections", row),
|
|
295
|
+
...typeof row["poolKey"] === "string" ? { poolKey: row["poolKey"] } : {}
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
var codec3 = {
|
|
299
|
+
mode: "strict",
|
|
300
|
+
typeSymbol: "@dan-ai-studio/dshopencodego#RequestLogSnapshot",
|
|
301
|
+
schema: { parse: parseRequestLogSnapshot },
|
|
302
|
+
create: () => ({ parse: parseRequestLogSnapshot })
|
|
303
|
+
};
|
|
304
|
+
var requestLogRemote = {
|
|
305
|
+
package: "@dan-ai-studio/dshopencodego",
|
|
306
|
+
descriptors: [
|
|
307
|
+
{
|
|
308
|
+
id: "@dan-ai-studio/dshopencodego#opencodeGoRequestLog/readLog",
|
|
309
|
+
service: "opencodeGoRequestLog",
|
|
310
|
+
namespace: "opencodeGoRequestLog",
|
|
311
|
+
method: "readLog",
|
|
312
|
+
invocation: { kind: "direct" },
|
|
313
|
+
parameters: [],
|
|
314
|
+
result: codec3
|
|
315
|
+
}
|
|
316
|
+
]
|
|
317
|
+
};
|
|
318
|
+
|
|
210
319
|
// src/update/contract.ts
|
|
211
320
|
function parseUpdateStatus(value) {
|
|
212
321
|
if (value === null || typeof value !== "object") throw new Error("invalid update reading");
|
|
@@ -226,7 +335,7 @@ function parseUpdateStatus(value) {
|
|
|
226
335
|
checked: row["checked"]
|
|
227
336
|
};
|
|
228
337
|
}
|
|
229
|
-
var
|
|
338
|
+
var codec4 = (typeSymbol, parse) => ({
|
|
230
339
|
mode: "strict",
|
|
231
340
|
typeSymbol,
|
|
232
341
|
schema: { parse },
|
|
@@ -242,7 +351,7 @@ var updateRemote = {
|
|
|
242
351
|
method: "readUpdate",
|
|
243
352
|
invocation: { kind: "direct" },
|
|
244
353
|
parameters: [],
|
|
245
|
-
result:
|
|
354
|
+
result: codec4("@dan-ai-studio/dshopencodego#UpdateStatus", parseUpdateStatus)
|
|
246
355
|
},
|
|
247
356
|
{
|
|
248
357
|
id: "@dan-ai-studio/dshopencodego#opencodeGoUpdate/refreshUpdate",
|
|
@@ -251,7 +360,7 @@ var updateRemote = {
|
|
|
251
360
|
method: "refreshUpdate",
|
|
252
361
|
invocation: { kind: "direct" },
|
|
253
362
|
parameters: [],
|
|
254
|
-
result:
|
|
363
|
+
result: codec4("@dan-ai-studio/dshopencodego#UpdateStatus", parseUpdateStatus)
|
|
255
364
|
}
|
|
256
365
|
]
|
|
257
366
|
};
|
|
@@ -278,22 +387,22 @@ function parseUsageWindows(value) {
|
|
|
278
387
|
function parseTotals(value) {
|
|
279
388
|
if (value === null || typeof value !== "object") throw new Error("invalid meter totals");
|
|
280
389
|
const row = value;
|
|
281
|
-
const
|
|
390
|
+
const count3 = (key) => {
|
|
282
391
|
const entry = row[key];
|
|
283
392
|
if (typeof entry !== "number" || !Number.isFinite(entry) || entry < 0) throw new Error(`invalid meter field "${key}"`);
|
|
284
393
|
return entry;
|
|
285
394
|
};
|
|
286
|
-
const optionalCount = (key) => row[key] === void 0 ? void 0 :
|
|
395
|
+
const optionalCount = (key) => row[key] === void 0 ? void 0 : count3(key);
|
|
287
396
|
const reasoningTokens = optionalCount("reasoningTokens");
|
|
288
397
|
const estimatedUSD = optionalCount("estimatedUSD");
|
|
289
398
|
const unpricedTokens = optionalCount("unpricedTokens");
|
|
290
399
|
return {
|
|
291
|
-
calls:
|
|
292
|
-
inputTokens:
|
|
293
|
-
outputTokens:
|
|
294
|
-
cacheReadTokens:
|
|
295
|
-
cacheWriteTokens:
|
|
296
|
-
totalTokens:
|
|
400
|
+
calls: count3("calls"),
|
|
401
|
+
inputTokens: count3("inputTokens"),
|
|
402
|
+
outputTokens: count3("outputTokens"),
|
|
403
|
+
cacheReadTokens: count3("cacheReadTokens"),
|
|
404
|
+
cacheWriteTokens: count3("cacheWriteTokens"),
|
|
405
|
+
totalTokens: count3("totalTokens"),
|
|
297
406
|
...reasoningTokens === void 0 ? {} : { reasoningTokens },
|
|
298
407
|
...estimatedUSD === void 0 ? {} : { estimatedUSD },
|
|
299
408
|
...unpricedTokens === void 0 ? {} : { unpricedTokens }
|
|
@@ -317,7 +426,7 @@ function parseGoMeter(value) {
|
|
|
317
426
|
})
|
|
318
427
|
};
|
|
319
428
|
}
|
|
320
|
-
var
|
|
429
|
+
var codec5 = (typeSymbol, parse) => ({
|
|
321
430
|
mode: "strict",
|
|
322
431
|
typeSymbol,
|
|
323
432
|
schema: { parse },
|
|
@@ -333,7 +442,7 @@ var usageRemote = {
|
|
|
333
442
|
method: "readWindows",
|
|
334
443
|
invocation: { kind: "direct" },
|
|
335
444
|
parameters: [],
|
|
336
|
-
result:
|
|
445
|
+
result: codec5("@dan-ai-studio/dshopencodego#GoUsageWindows", parseUsageWindows)
|
|
337
446
|
},
|
|
338
447
|
{
|
|
339
448
|
id: "@dan-ai-studio/dshopencodego#opencodeGoUsage/readMeter",
|
|
@@ -342,7 +451,7 @@ var usageRemote = {
|
|
|
342
451
|
method: "readMeter",
|
|
343
452
|
invocation: { kind: "direct" },
|
|
344
453
|
parameters: [],
|
|
345
|
-
result:
|
|
454
|
+
result: codec5("@dan-ai-studio/dshopencodego#GoMeter", parseGoMeter)
|
|
346
455
|
}
|
|
347
456
|
]
|
|
348
457
|
};
|
|
@@ -388,6 +497,70 @@ var en = {
|
|
|
388
497
|
refreshHint: "How long requests and the model picker reuse one listing.",
|
|
389
498
|
keepAliveLabel: "Connection kept idle (seconds)",
|
|
390
499
|
keepAliveHint: "How long a connection to the gateway is held between requests. Longer pauses in a conversation cost one handshake each; the timer restarts on every answer.",
|
|
500
|
+
requestLogTitle: "Request log",
|
|
501
|
+
requestLogHint: "Per-request records for troubleshooting. Off by default; enabling it does not change what requests do.",
|
|
502
|
+
requestLogPageHint: "One row per request. The table scrolls; the filters stay put.",
|
|
503
|
+
requestLogEnabled: "Record requests",
|
|
504
|
+
requestLogDebug: "Debug detail",
|
|
505
|
+
requestLogDebugHint: "Pool events and full session ids. Otherwise sessions are truncated to 8 characters.",
|
|
506
|
+
requestLogMaxEntries: "Keep at most (entries)",
|
|
507
|
+
requestLogMaxEntriesHint: "50 to 500; oldest entries are dropped first. Default 200.",
|
|
508
|
+
requestLogOpen: "Open request log",
|
|
509
|
+
requestLogClose: "Close",
|
|
510
|
+
requestLogRefresh: "Refresh",
|
|
511
|
+
requestLogEmpty: "No requests recorded. Turn the log on, then make a request.",
|
|
512
|
+
requestLogDisabled: "The request log is off.",
|
|
513
|
+
requestLogFilterModel: "Model",
|
|
514
|
+
requestLogFilterModelAll: "All models",
|
|
515
|
+
requestLogFilterResult: "Result",
|
|
516
|
+
requestLogResultAll: "All",
|
|
517
|
+
requestLogResultOk: "Succeeded",
|
|
518
|
+
requestLogResultFail: "Failed",
|
|
519
|
+
requestLogSlowOnly: "Slow only",
|
|
520
|
+
requestLogSlowSeconds: "slower than (seconds)",
|
|
521
|
+
requestLogFilterSession: "Session contains",
|
|
522
|
+
requestLogOnlySession: "this session only",
|
|
523
|
+
requestLogGroupBy: "Group by",
|
|
524
|
+
requestLogGroupNone: "None",
|
|
525
|
+
requestLogGroupSession: "Session",
|
|
526
|
+
requestLogGroupModel: "Model",
|
|
527
|
+
requestLogGroupResult: "Result",
|
|
528
|
+
requestLogPagePrev: "Previous",
|
|
529
|
+
requestLogPageNext: "Next",
|
|
530
|
+
requestLogPageOf: "of",
|
|
531
|
+
requestLogReuse: "Connection reuse",
|
|
532
|
+
requestLogReuseHint: "Share of recorded requests that reused a kept-alive connection, estimated from new sockets vs recorded requests.",
|
|
533
|
+
requestLogDropped: "dropped",
|
|
534
|
+
requestLogColTime: "Time",
|
|
535
|
+
requestLogColModel: "Model",
|
|
536
|
+
requestLogColSession: "Session",
|
|
537
|
+
requestLogColIn: "In",
|
|
538
|
+
requestLogColOut: "Out",
|
|
539
|
+
requestLogColCache: "Cached",
|
|
540
|
+
requestLogColLatency: "Latency",
|
|
541
|
+
requestLogColTps: "tok/s",
|
|
542
|
+
requestLogColFirstToken: "First token",
|
|
543
|
+
requestLogColStatus: "Status",
|
|
544
|
+
requestLogDetailRequest: "Request",
|
|
545
|
+
requestLogDetailTiming: "Timing",
|
|
546
|
+
requestLogDetailResult: "Result",
|
|
547
|
+
requestLogDetailMethod: "Method",
|
|
548
|
+
requestLogDetailUrl: "URL",
|
|
549
|
+
requestLogDetailSession: "Session",
|
|
550
|
+
requestLogDetailPool: "Pool",
|
|
551
|
+
requestLogDetailError: "Error",
|
|
552
|
+
requestLogDetailTokens: "Tokens",
|
|
553
|
+
requestLogDetailHeaders: "Headers",
|
|
554
|
+
requestLogDetailUserAgent: "User-Agent",
|
|
555
|
+
requestLogDetailShape: "Shape",
|
|
556
|
+
requestLogDetailMessages: "messages",
|
|
557
|
+
requestLogDetailTools: "tools",
|
|
558
|
+
requestLogDetailHasImage: "with images",
|
|
559
|
+
requestLogStatRequests: "Requests",
|
|
560
|
+
requestLogStatFailures: "Failures",
|
|
561
|
+
requestLogStatLatency: "Mean latency",
|
|
562
|
+
requestLogStatFirstToken: "Mean first token",
|
|
563
|
+
requestLogStatTps: "Mean tok/s",
|
|
391
564
|
writeRejected: "The settings write was rejected (the namespace was reloaded) \u2014 try again",
|
|
392
565
|
writeFailed: "The settings write failed",
|
|
393
566
|
filterPlaceholder: "Filter by name or id",
|
|
@@ -500,6 +673,70 @@ var zh = {
|
|
|
500
673
|
refreshHint: "\u8BF7\u6C42\u4E0E\u6A21\u578B\u9009\u62E9\u5668\u590D\u7528\u540C\u4E00\u4EFD\u5217\u8868\u7684\u65F6\u957F\u3002",
|
|
501
674
|
keepAliveLabel: "\u8FDE\u63A5\u7A7A\u95F2\u4FDD\u7559\uFF08\u79D2\uFF09",
|
|
502
675
|
keepAliveHint: "\u4E0E\u7F51\u5173\u7684\u8FDE\u63A5\u5728\u4E24\u6B21\u8BF7\u6C42\u4E4B\u95F4\u4FDD\u7559\u591A\u4E45\u3002\u5BF9\u8BDD\u4E2D\u6BCF\u6B21\u505C\u987F\u8F83\u4E45\u90FD\u8981\u91CD\u65B0\u63E1\u624B\u4E00\u6B21\uFF1B\u6BCF\u6B21\u6536\u5230\u56DE\u7B54\u540E\u8BA1\u65F6\u90FD\u4F1A\u91CD\u65B0\u5F00\u59CB\u3002",
|
|
676
|
+
requestLogTitle: "\u8BF7\u6C42\u65E5\u5FD7",
|
|
677
|
+
requestLogHint: "\u6392\u67E5\u7528\u7684\u9010\u8BF7\u6C42\u8BB0\u5F55\u3002\u9ED8\u8BA4\u5173\u95ED\uFF1B\u6253\u5F00\u5B83\u4E0D\u4F1A\u6539\u53D8\u8BF7\u6C42\u672C\u8EAB\u7684\u884C\u4E3A\u3002",
|
|
678
|
+
requestLogPageHint: "\u6BCF\u4E2A\u8BF7\u6C42\u4E00\u884C\u3002\u8868\u683C\u6EDA\u52A8\uFF0C\u7B5B\u9009\u680F\u56FA\u5B9A\u5728\u4E0A\u65B9\u3002",
|
|
679
|
+
requestLogEnabled: "\u8BB0\u5F55\u8BF7\u6C42",
|
|
680
|
+
requestLogDebug: "\u6392\u9519\u8BE6\u60C5",
|
|
681
|
+
requestLogDebugHint: "\u8FDE\u63A5\u6C60\u4E8B\u4EF6\u4E0E\u5B8C\u6574\u4F1A\u8BDD id\u3002\u4E0D\u5F00\u5219\u4F1A\u8BDD\u53EA\u4FDD\u7559\u524D 8 \u4F4D\u3002",
|
|
682
|
+
requestLogMaxEntries: "\u6700\u591A\u4FDD\u7559\uFF08\u6761\uFF09",
|
|
683
|
+
requestLogMaxEntriesHint: "50\uFF5E500 \u6761\uFF0C\u8D85\u9650\u4E22\u5F03\u6700\u65E7\u7684\u3002\u9ED8\u8BA4 200 \u6761\u3002",
|
|
684
|
+
requestLogOpen: "\u6253\u5F00\u8BF7\u6C42\u65E5\u5FD7",
|
|
685
|
+
requestLogClose: "\u5173\u95ED",
|
|
686
|
+
requestLogRefresh: "\u5237\u65B0",
|
|
687
|
+
requestLogEmpty: "\u6682\u65E0\u8BB0\u5F55\u3002\u5148\u6253\u5F00\u65E5\u5FD7\u5F00\u5173\uFF0C\u518D\u53D1\u8D77\u4E00\u6B21\u8BF7\u6C42\u3002",
|
|
688
|
+
requestLogDisabled: "\u8BF7\u6C42\u65E5\u5FD7\u672A\u5F00\u542F\u3002",
|
|
689
|
+
requestLogFilterModel: "\u6A21\u578B",
|
|
690
|
+
requestLogFilterModelAll: "\u5168\u90E8\u6A21\u578B",
|
|
691
|
+
requestLogFilterResult: "\u7ED3\u679C",
|
|
692
|
+
requestLogResultAll: "\u5168\u90E8",
|
|
693
|
+
requestLogResultOk: "\u6210\u529F",
|
|
694
|
+
requestLogResultFail: "\u5931\u8D25",
|
|
695
|
+
requestLogSlowOnly: "\u53EA\u770B\u6162\u8BF7\u6C42",
|
|
696
|
+
requestLogSlowSeconds: "\u6162\u4E8E\uFF08\u79D2\uFF09",
|
|
697
|
+
requestLogFilterSession: "\u4F1A\u8BDD\u5305\u542B",
|
|
698
|
+
requestLogOnlySession: "\u4EC5\u672C\u4F1A\u8BDD",
|
|
699
|
+
requestLogGroupBy: "\u5206\u7EC4",
|
|
700
|
+
requestLogGroupNone: "\u4E0D\u5206\u7EC4",
|
|
701
|
+
requestLogGroupSession: "\u6309\u4F1A\u8BDD",
|
|
702
|
+
requestLogGroupModel: "\u6309\u6A21\u578B",
|
|
703
|
+
requestLogGroupResult: "\u6309\u7ED3\u679C",
|
|
704
|
+
requestLogPagePrev: "\u4E0A\u4E00\u9875",
|
|
705
|
+
requestLogPageNext: "\u4E0B\u4E00\u9875",
|
|
706
|
+
requestLogPageOf: "\uFF0F\u5171",
|
|
707
|
+
requestLogReuse: "\u8FDE\u63A5\u590D\u7528\u7387",
|
|
708
|
+
requestLogReuseHint: "\u590D\u7528\u4FDD\u6D3B\u8FDE\u63A5\u7684\u8BF7\u6C42\u5360\u6BD4\uFF0C\u7528\u65B0\u5EFA\u8FDE\u63A5\u6570\u4E0E\u5DF2\u8BB0\u5F55\u8BF7\u6C42\u6570\u4F30\u7B97\u3002",
|
|
709
|
+
requestLogDropped: "\u5DF2\u4E22\u5F03",
|
|
710
|
+
requestLogColTime: "\u65F6\u95F4",
|
|
711
|
+
requestLogColModel: "\u6A21\u578B",
|
|
712
|
+
requestLogColSession: "\u4F1A\u8BDD",
|
|
713
|
+
requestLogColIn: "\u8F93\u5165",
|
|
714
|
+
requestLogColOut: "\u8F93\u51FA",
|
|
715
|
+
requestLogColCache: "\u7F13\u5B58",
|
|
716
|
+
requestLogColLatency: "\u8017\u65F6",
|
|
717
|
+
requestLogColTps: "tok/s",
|
|
718
|
+
requestLogColFirstToken: "\u9996\u5B57",
|
|
719
|
+
requestLogColStatus: "\u72B6\u6001",
|
|
720
|
+
requestLogDetailRequest: "\u8BF7\u6C42",
|
|
721
|
+
requestLogDetailTiming: "\u8017\u65F6",
|
|
722
|
+
requestLogDetailResult: "\u7ED3\u679C",
|
|
723
|
+
requestLogDetailMethod: "\u65B9\u6CD5",
|
|
724
|
+
requestLogDetailUrl: "\u5730\u5740",
|
|
725
|
+
requestLogDetailSession: "\u4F1A\u8BDD",
|
|
726
|
+
requestLogDetailPool: "\u8FDE\u63A5\u6C60",
|
|
727
|
+
requestLogDetailError: "\u9519\u8BEF",
|
|
728
|
+
requestLogDetailTokens: "Token",
|
|
729
|
+
requestLogDetailHeaders: "\u8BF7\u6C42\u5934",
|
|
730
|
+
requestLogDetailUserAgent: "User-Agent",
|
|
731
|
+
requestLogDetailShape: "\u8BF7\u6C42\u6784\u6210",
|
|
732
|
+
requestLogDetailMessages: "\u6761\u6D88\u606F",
|
|
733
|
+
requestLogDetailTools: "\u4E2A\u5DE5\u5177",
|
|
734
|
+
requestLogDetailHasImage: "\u542B\u56FE\u7247",
|
|
735
|
+
requestLogStatRequests: "\u8BF7\u6C42\u6570",
|
|
736
|
+
requestLogStatFailures: "\u5931\u8D25\u6570",
|
|
737
|
+
requestLogStatLatency: "\u5E73\u5747\u8017\u65F6",
|
|
738
|
+
requestLogStatFirstToken: "\u5E73\u5747\u9996\u5B57",
|
|
739
|
+
requestLogStatTps: "\u5E73\u5747 tok/s",
|
|
503
740
|
writeRejected: "\u8BBE\u7F6E\u5199\u5165\u88AB\u62D2\u7EDD\uFF08\u5DF2\u91CD\u65B0\u8F7D\u5165\uFF09\uFF0C\u8BF7\u91CD\u8BD5",
|
|
504
741
|
writeFailed: "\u8BBE\u7F6E\u5199\u5165\u5931\u8D25",
|
|
505
742
|
filterPlaceholder: "\u6309\u540D\u79F0\u6216 ID \u7B5B\u9009",
|
|
@@ -588,6 +825,11 @@ var MAX_KEEP_ALIVE_TIMEOUT_SECONDS = 1800;
|
|
|
588
825
|
var DEFAULT_KEEP_ALIVE_TIMEOUT_MS = DEFAULT_KEEP_ALIVE_TIMEOUT_SECONDS * 1e3;
|
|
589
826
|
var MAX_KEEP_ALIVE_TIMEOUT_MS = MAX_KEEP_ALIVE_TIMEOUT_SECONDS * 1e3;
|
|
590
827
|
|
|
828
|
+
// src/request-log/limits.ts
|
|
829
|
+
var DEFAULT_REQUEST_LOG_MAX_ENTRIES = 200;
|
|
830
|
+
var MIN_REQUEST_LOG_MAX_ENTRIES = 50;
|
|
831
|
+
var MAX_REQUEST_LOG_MAX_ENTRIES = 500;
|
|
832
|
+
|
|
591
833
|
// src/go-limits.ts
|
|
592
834
|
var SEED_TRANSCRIBED = "2026-09-25";
|
|
593
835
|
function monthlyRequestsRank(quota) {
|
|
@@ -629,18 +871,18 @@ function isIPv6(value) {
|
|
|
629
871
|
const head = groups(halves[0] ?? "");
|
|
630
872
|
const tail = halves.length === 2 ? groups(halves[1] ?? "") : [];
|
|
631
873
|
const all = [...head, ...tail];
|
|
632
|
-
let
|
|
874
|
+
let count3 = 0;
|
|
633
875
|
for (const [index, group] of all.entries()) {
|
|
634
876
|
if (group.includes(".")) {
|
|
635
877
|
if (index !== all.length - 1) return false;
|
|
636
878
|
if (!isDottedQuad(group)) return false;
|
|
637
|
-
|
|
879
|
+
count3 += 2;
|
|
638
880
|
continue;
|
|
639
881
|
}
|
|
640
882
|
if (!/^[0-9a-fA-F]{1,4}$/.test(group)) return false;
|
|
641
|
-
|
|
883
|
+
count3 += 1;
|
|
642
884
|
}
|
|
643
|
-
return halves.length === 2 ?
|
|
885
|
+
return halves.length === 2 ? count3 <= 7 : count3 === 8;
|
|
644
886
|
}
|
|
645
887
|
function isAddress(value) {
|
|
646
888
|
const trimmed = value.trim();
|
|
@@ -749,11 +991,17 @@ function settingsOf(value) {
|
|
|
749
991
|
const pins = record["pinnedAddresses"];
|
|
750
992
|
const pinEntries = pins !== null && typeof pins === "object" ? Object.entries(pins).filter(([, address]) => typeof address === "string") : [];
|
|
751
993
|
const keepAlive = record["keepAliveTimeoutMs"];
|
|
994
|
+
const requestLogEnabled = record["requestLogEnabled"];
|
|
995
|
+
const requestLogDebug = record["requestLogDebug"];
|
|
996
|
+
const requestLogMaxEntries = record["requestLogMaxEntries"];
|
|
752
997
|
return {
|
|
753
998
|
modelVisibility: Object.fromEntries(entries),
|
|
754
999
|
refreshMinutes: minutes,
|
|
755
1000
|
pinnedAddresses: Object.fromEntries(pinEntries),
|
|
756
|
-
keepAliveTimeoutMs: typeof keepAlive === "number" ? keepAlive : DEFAULT_KEEP_ALIVE_TIMEOUT_MS
|
|
1001
|
+
keepAliveTimeoutMs: typeof keepAlive === "number" ? keepAlive : DEFAULT_KEEP_ALIVE_TIMEOUT_MS,
|
|
1002
|
+
requestLogEnabled: typeof requestLogEnabled === "boolean" ? requestLogEnabled : false,
|
|
1003
|
+
requestLogDebug: typeof requestLogDebug === "boolean" ? requestLogDebug : false,
|
|
1004
|
+
requestLogMaxEntries: typeof requestLogMaxEntries === "number" ? requestLogMaxEntries : DEFAULT_REQUEST_LOG_MAX_ENTRIES
|
|
757
1005
|
};
|
|
758
1006
|
}
|
|
759
1007
|
var SectionController = class _SectionController {
|
|
@@ -843,6 +1091,18 @@ var SectionController = class _SectionController {
|
|
|
843
1091
|
});
|
|
844
1092
|
}
|
|
845
1093
|
}
|
|
1094
|
+
/**
|
|
1095
|
+
* Read one request-log snapshot for the viewer. The viewer opens it on
|
|
1096
|
+
* demand and refreshes it when asked; nothing polls, so a closed viewer
|
|
1097
|
+
* costs no wire traffic at all.
|
|
1098
|
+
*/
|
|
1099
|
+
async readRequestLog() {
|
|
1100
|
+
const remote = this.services.remote.opencodeGoRequestLog;
|
|
1101
|
+
if (remote === void 0) throw new Error("the request-log Remote is not mounted");
|
|
1102
|
+
const result = await remote.readLog();
|
|
1103
|
+
if (!result.ok) throw result.error;
|
|
1104
|
+
return result.value;
|
|
1105
|
+
}
|
|
846
1106
|
/**
|
|
847
1107
|
* Pin the gateway to one address.
|
|
848
1108
|
*
|
|
@@ -1053,8 +1313,8 @@ var SectionController = class _SectionController {
|
|
|
1053
1313
|
* the UI never waits on the Host round trip and a burst of clicks becomes a
|
|
1054
1314
|
* single write of the final dict.
|
|
1055
1315
|
*/
|
|
1056
|
-
setVisibility(
|
|
1057
|
-
this.mergeVisibility({ [
|
|
1316
|
+
setVisibility(id4, enabled) {
|
|
1317
|
+
this.mergeVisibility({ [id4]: enabled });
|
|
1058
1318
|
}
|
|
1059
1319
|
/**
|
|
1060
1320
|
* Set every configurable model at once (select-all / select-none).
|
|
@@ -1153,6 +1413,49 @@ var SectionController = class _SectionController {
|
|
|
1153
1413
|
() => this.set({ settings: { ...current, keepAliveTimeoutMs: milliseconds } })
|
|
1154
1414
|
);
|
|
1155
1415
|
}
|
|
1416
|
+
/**
|
|
1417
|
+
* Flip the request-log master switch. Off (the default) means no record is
|
|
1418
|
+
* kept and the request path reads exactly as without the log.
|
|
1419
|
+
*/
|
|
1420
|
+
async setRequestLogEnabled(enabled) {
|
|
1421
|
+
const scope = this.services.scope;
|
|
1422
|
+
const current = this.state.settings;
|
|
1423
|
+
if (scope === void 0 || current === void 0 || !this.state.writable) return;
|
|
1424
|
+
if (typeof enabled !== "boolean") return;
|
|
1425
|
+
await this.write(
|
|
1426
|
+
() => scope.set("requestLogEnabled", enabled),
|
|
1427
|
+
() => this.set({ settings: { ...current, requestLogEnabled: enabled } })
|
|
1428
|
+
);
|
|
1429
|
+
}
|
|
1430
|
+
/**
|
|
1431
|
+
* Flip request-log debug detail. Only recorded while the master switch is
|
|
1432
|
+
* on; the page does not enforce the pairing, the recorder does.
|
|
1433
|
+
*/
|
|
1434
|
+
async setRequestLogDebug(debug) {
|
|
1435
|
+
const scope = this.services.scope;
|
|
1436
|
+
const current = this.state.settings;
|
|
1437
|
+
if (scope === void 0 || current === void 0 || !this.state.writable) return;
|
|
1438
|
+
if (typeof debug !== "boolean") return;
|
|
1439
|
+
await this.write(
|
|
1440
|
+
() => scope.set("requestLogDebug", debug),
|
|
1441
|
+
() => this.set({ settings: { ...current, requestLogDebug: debug } })
|
|
1442
|
+
);
|
|
1443
|
+
}
|
|
1444
|
+
/**
|
|
1445
|
+
* Set how many request-log entries the Host keeps, clamped to the schema's
|
|
1446
|
+
* own bounds. A lowered bound trims on the next read; raising it backfills
|
|
1447
|
+
* nothing.
|
|
1448
|
+
*/
|
|
1449
|
+
async setRequestLogMaxEntries(entries) {
|
|
1450
|
+
const scope = this.services.scope;
|
|
1451
|
+
const current = this.state.settings;
|
|
1452
|
+
if (scope === void 0 || current === void 0 || !this.state.writable) return;
|
|
1453
|
+
if (!Number.isSafeInteger(entries) || entries < MIN_REQUEST_LOG_MAX_ENTRIES || entries > MAX_REQUEST_LOG_MAX_ENTRIES) return;
|
|
1454
|
+
await this.write(
|
|
1455
|
+
() => scope.set("requestLogMaxEntries", entries),
|
|
1456
|
+
() => this.set({ settings: { ...current, requestLogMaxEntries: entries } })
|
|
1457
|
+
);
|
|
1458
|
+
}
|
|
1156
1459
|
async write(operation, onAccepted) {
|
|
1157
1460
|
this.set({ saving: true });
|
|
1158
1461
|
try {
|
|
@@ -1315,7 +1618,7 @@ function updateFailureText(message, t) {
|
|
|
1315
1618
|
if (message === "pending-builds") return t("updatePendingBuilds");
|
|
1316
1619
|
return message;
|
|
1317
1620
|
}
|
|
1318
|
-
function Section({ controller, t, getLocale }) {
|
|
1621
|
+
function Section({ controller, t, getLocale, openRequestLog }) {
|
|
1319
1622
|
const state = (0, import_react.useSyncExternalStore)(controller.subscribe, controller.snapshot, controller.snapshot);
|
|
1320
1623
|
const [keyDraft, setKeyDraft] = (0, import_react.useState)("");
|
|
1321
1624
|
const [pinDraft, setPinDraft] = (0, import_react.useState)("");
|
|
@@ -1550,6 +1853,67 @@ function Section({ controller, t, getLocale }) {
|
|
|
1550
1853
|
),
|
|
1551
1854
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: section_default.hint, children: t("keepAliveHint") })
|
|
1552
1855
|
] }),
|
|
1856
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: section_default.row, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: t("requestLogTitle") }) }),
|
|
1857
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: section_default.hint, children: t("requestLogHint") }),
|
|
1858
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: section_default.row, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: section_default.hint, children: [
|
|
1859
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1860
|
+
"input",
|
|
1861
|
+
{
|
|
1862
|
+
type: "checkbox",
|
|
1863
|
+
checked: state.settings?.requestLogEnabled ?? false,
|
|
1864
|
+
disabled: !editable || state.saving,
|
|
1865
|
+
onChange: (event) => {
|
|
1866
|
+
void act(async () => {
|
|
1867
|
+
await controller.setRequestLogEnabled(event.target.checked);
|
|
1868
|
+
});
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
),
|
|
1872
|
+
` ${t("requestLogEnabled")}`
|
|
1873
|
+
] }) }),
|
|
1874
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: section_default.row, children: [
|
|
1875
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: section_default.hint, children: [
|
|
1876
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1877
|
+
"input",
|
|
1878
|
+
{
|
|
1879
|
+
type: "checkbox",
|
|
1880
|
+
checked: state.settings?.requestLogDebug ?? false,
|
|
1881
|
+
disabled: !editable || state.saving,
|
|
1882
|
+
onChange: (event) => {
|
|
1883
|
+
void act(async () => {
|
|
1884
|
+
await controller.setRequestLogDebug(event.target.checked);
|
|
1885
|
+
});
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1888
|
+
),
|
|
1889
|
+
` ${t("requestLogDebug")}`
|
|
1890
|
+
] }),
|
|
1891
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: section_default.hint, children: t("requestLogDebugHint") })
|
|
1892
|
+
] }),
|
|
1893
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: section_default.row, children: [
|
|
1894
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: section_default.hint, htmlFor: "dshopencodego-requestlog-max", children: t("requestLogMaxEntries") }),
|
|
1895
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1896
|
+
"input",
|
|
1897
|
+
{
|
|
1898
|
+
id: "dshopencodego-requestlog-max",
|
|
1899
|
+
className: section_default.number,
|
|
1900
|
+
type: "number",
|
|
1901
|
+
min: MIN_REQUEST_LOG_MAX_ENTRIES,
|
|
1902
|
+
max: MAX_REQUEST_LOG_MAX_ENTRIES,
|
|
1903
|
+
disabled: !editable || state.saving,
|
|
1904
|
+
value: state.settings?.requestLogMaxEntries ?? "",
|
|
1905
|
+
onChange: (event) => {
|
|
1906
|
+
void act(async () => {
|
|
1907
|
+
await controller.setRequestLogMaxEntries(Number(event.target.value));
|
|
1908
|
+
});
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
),
|
|
1912
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: section_default.hint, children: t("requestLogMaxEntriesHint") })
|
|
1913
|
+
] }),
|
|
1914
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: section_default.row, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: section_default.button, onClick: () => {
|
|
1915
|
+
openRequestLog?.();
|
|
1916
|
+
}, children: t("requestLogOpen") }) }),
|
|
1553
1917
|
state.writeFailure !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: section_default.warn, children: state.writeFailure.kind === "rejected" ? t("writeRejected") : state.writeFailure.message.length === 0 ? t("writeFailed") : `${t("writeFailed")}: ${state.writeFailure.message}` }),
|
|
1554
1918
|
reading !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: section_default.row, children: [
|
|
1555
1919
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -1658,22 +2022,406 @@ function Section({ controller, t, getLocale }) {
|
|
|
1658
2022
|
] });
|
|
1659
2023
|
}
|
|
1660
2024
|
|
|
1661
|
-
// src/client/
|
|
2025
|
+
// src/client/RequestLogPage.tsx
|
|
1662
2026
|
var import_react2 = require("react");
|
|
2027
|
+
var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
1663
2028
|
|
|
1664
|
-
// plugin-css:/home/runner/work/dshopencodego/dshopencodego/src/client/
|
|
1665
|
-
var id2 = "@dan-ai-studio/dshopencodego/
|
|
2029
|
+
// plugin-css:/home/runner/work/dshopencodego/dshopencodego/src/client/request-log.module.css
|
|
2030
|
+
var id2 = "@dan-ai-studio/dshopencodego/request-log.module.css";
|
|
1666
2031
|
if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id2) + "]")) {
|
|
1667
2032
|
const style = document.createElement("style");
|
|
1668
2033
|
style.dataset.plugin = "@dan-ai-studio/dshopencodego";
|
|
1669
2034
|
style.dataset.pluginCss = id2;
|
|
2035
|
+
style.textContent = ".Lx7MOq_page{box-sizing:border-box;background:var(--dsw-alias-bg-base);height:100%;min-height:0;color:var(--dsw-alias-label-primary);flex-direction:column;display:flex;overflow:hidden}.Lx7MOq_head{flex-wrap:wrap;flex:none;align-items:center;gap:12px;padding:20px clamp(16px,3vw,32px) 12px;display:flex}.Lx7MOq_headText{min-width:0}.Lx7MOq_title{margin:0;font-size:20px;font-weight:500;line-height:28px}.Lx7MOq_subtitle{color:var(--dsw-alias-label-secondary);margin:4px 0 0;font-size:13px;line-height:20px}.Lx7MOq_headActions{flex:none;align-items:center;gap:8px;margin-left:auto;display:flex}.Lx7MOq_button{border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-layer-1);height:28px;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;align-items:center;gap:6px;padding:0 12px;font-size:13px;display:inline-flex}.Lx7MOq_button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.Lx7MOq_button:disabled{cursor:default;opacity:.5}.Lx7MOq_summary{flex-wrap:wrap;flex:none;gap:8px;padding:0 clamp(16px,3vw,32px) 12px;display:flex}.Lx7MOq_card{border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);flex-direction:column;gap:2px;min-width:104px;padding:8px 12px;display:flex}.Lx7MOq_cardLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:16px}.Lx7MOq_cardValue{font-variant-numeric:tabular-nums;font-size:16px;font-weight:500;line-height:22px}.Lx7MOq_cardError .Lx7MOq_cardValue{color:var(--dsw-alias-state-error-primary)}.Lx7MOq_cardWarn .Lx7MOq_cardValue{color:var(--dsw-alias-state-warn-primary)}.Lx7MOq_toolbar{flex-wrap:wrap;flex:none;align-items:center;gap:8px 12px;padding:0 clamp(16px,3vw,32px) 12px;display:flex}.Lx7MOq_field{color:var(--dsw-alias-label-secondary);align-items:center;gap:6px;font-size:13px;line-height:20px;display:inline-flex}.Lx7MOq_select,.Lx7MOq_input{border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-layer-1);height:28px;color:var(--dsw-alias-label-primary);font:inherit;padding:0 8px;font-size:13px}.Lx7MOq_input{width:160px}.Lx7MOq_inputNumber{width:72px}.Lx7MOq_checkbox{accent-color:var(--dsw-alias-brand-primary)}.Lx7MOq_tableWrap{border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);flex:1;min-height:0;margin:0 clamp(16px,3vw,32px);overflow:auto}.Lx7MOq_table{border-collapse:separate;border-spacing:0;width:100%;min-width:940px;font-size:13px;line-height:20px}.Lx7MOq_table th{z-index:1;border-bottom:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-tertiary);text-align:left;white-space:nowrap;padding:8px 10px;font-size:12px;font-weight:500;position:sticky;top:0}.Lx7MOq_table td{border-bottom:1px solid var(--dsw-alias-border-l1);white-space:nowrap;font-variant-numeric:tabular-nums;padding:6px 10px}.Lx7MOq_table tbody tr:last-child td{border-bottom:none}.Lx7MOq_row{cursor:pointer}.Lx7MOq_row:hover td{background:var(--dsw-alias-interactive-bg-hover)}.Lx7MOq_rowOk td:first-child{box-shadow:inset 3px 0 0 var(--dsw-alias-border-l3)}.Lx7MOq_rowSlow td:first-child{box-shadow:inset 3px 0 0 var(--dsw-alias-state-warn-primary)}.Lx7MOq_rowFail td:first-child{box-shadow:inset 3px 0 0 var(--dsw-alias-state-error-primary)}.Lx7MOq_rowFail td:last-child,.Lx7MOq_rowSlow td:last-child{color:var(--dsw-alias-state-error-primary)}.Lx7MOq_group td{border-bottom:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);padding-top:12px;font-weight:500}.Lx7MOq_detail td{border-bottom:1px solid var(--dsw-alias-border-l1);white-space:normal;background:var(--dsw-alias-bg-layer-2);padding:12px 10px 16px}.Lx7MOq_detailGrid{grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:6px 24px;display:grid}.Lx7MOq_detailItem{gap:8px;min-width:0;font-size:13px;line-height:20px;display:flex}.Lx7MOq_detailLabel{color:var(--dsw-alias-label-tertiary);flex:none}.Lx7MOq_detailValue{overflow-wrap:anywhere;min-width:0;color:var(--dsw-alias-label-primary)}.Lx7MOq_mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px}.Lx7MOq_empty{text-align:center;color:var(--dsw-alias-label-tertiary);padding:48px 16px}.Lx7MOq_foot{color:var(--dsw-alias-label-tertiary);flex-wrap:wrap;flex:none;align-items:center;gap:12px;padding:12px clamp(16px,3vw,32px) 20px;font-size:12px;display:flex}.Lx7MOq_pager{align-items:center;gap:8px;margin-left:auto;display:flex}.Lx7MOq_notice{color:var(--dsw-alias-label-secondary);padding:0 clamp(16px,3vw,32px) 12px;font-size:13px;line-height:20px}.Lx7MOq_noticeError{color:var(--dsw-alias-state-error-primary)}";
|
|
2036
|
+
document.head.appendChild(style);
|
|
2037
|
+
}
|
|
2038
|
+
var request_log_default = { "button": "Lx7MOq_button", "card": "Lx7MOq_card", "cardError": "Lx7MOq_cardError", "cardLabel": "Lx7MOq_cardLabel", "cardValue": "Lx7MOq_cardValue", "cardWarn": "Lx7MOq_cardWarn", "checkbox": "Lx7MOq_checkbox", "detail": "Lx7MOq_detail", "detailGrid": "Lx7MOq_detailGrid", "detailItem": "Lx7MOq_detailItem", "detailLabel": "Lx7MOq_detailLabel", "detailValue": "Lx7MOq_detailValue", "empty": "Lx7MOq_empty", "field": "Lx7MOq_field", "foot": "Lx7MOq_foot", "group": "Lx7MOq_group", "head": "Lx7MOq_head", "headActions": "Lx7MOq_headActions", "headText": "Lx7MOq_headText", "input": "Lx7MOq_input", "inputNumber": "Lx7MOq_inputNumber", "mono": "Lx7MOq_mono", "notice": "Lx7MOq_notice", "noticeError": "Lx7MOq_noticeError", "page": "Lx7MOq_page", "pager": "Lx7MOq_pager", "row": "Lx7MOq_row", "rowFail": "Lx7MOq_rowFail", "rowOk": "Lx7MOq_rowOk", "rowSlow": "Lx7MOq_rowSlow", "select": "Lx7MOq_select", "subtitle": "Lx7MOq_subtitle", "summary": "Lx7MOq_summary", "table": "Lx7MOq_table", "tableWrap": "Lx7MOq_tableWrap", "title": "Lx7MOq_title", "toolbar": "Lx7MOq_toolbar" };
|
|
2039
|
+
|
|
2040
|
+
// src/client/RequestLogPage.tsx
|
|
2041
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
2042
|
+
var PAGE_SIZE = 50;
|
|
2043
|
+
function count2(value) {
|
|
2044
|
+
return value === void 0 ? "\u2014" : value.toLocaleString();
|
|
2045
|
+
}
|
|
2046
|
+
function duration(value) {
|
|
2047
|
+
if (value === void 0) return "\u2014";
|
|
2048
|
+
return value < 1e3 ? `${Math.round(value)}ms` : `${(value / 1e3).toFixed(2)}s`;
|
|
2049
|
+
}
|
|
2050
|
+
function rate2(value) {
|
|
2051
|
+
return value === void 0 ? "\u2014" : value.toFixed(1);
|
|
2052
|
+
}
|
|
2053
|
+
function average(values) {
|
|
2054
|
+
if (values.length === 0) return void 0;
|
|
2055
|
+
let sum = 0;
|
|
2056
|
+
for (const value of values) sum += value;
|
|
2057
|
+
return sum / values.length;
|
|
2058
|
+
}
|
|
2059
|
+
function groupKey(entry, groupBy) {
|
|
2060
|
+
switch (groupBy) {
|
|
2061
|
+
case "session":
|
|
2062
|
+
return entry.session === "" ? "\u2014" : entry.session;
|
|
2063
|
+
case "model":
|
|
2064
|
+
return entry.model;
|
|
2065
|
+
case "result":
|
|
2066
|
+
return entry.ok ? "ok" : entry.code ?? "fail";
|
|
2067
|
+
case "none":
|
|
2068
|
+
return void 0;
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
function RequestLogPage({ readLog, enabled, t, getLocale, sessionId }) {
|
|
2072
|
+
const [snapshot, setSnapshot] = (0, import_react2.useState)(void 0);
|
|
2073
|
+
const [failure, setFailure] = (0, import_react2.useState)(void 0);
|
|
2074
|
+
const [refreshing, setRefreshing] = (0, import_react2.useState)(false);
|
|
2075
|
+
const [model, setModel] = (0, import_react2.useState)("all");
|
|
2076
|
+
const [result, setResult] = (0, import_react2.useState)("all");
|
|
2077
|
+
const [slowOnly, setSlowOnly] = (0, import_react2.useState)(false);
|
|
2078
|
+
const [slowSeconds, setSlowSeconds] = (0, import_react2.useState)(5);
|
|
2079
|
+
const [sessionQuery, setSessionQuery] = (0, import_react2.useState)("");
|
|
2080
|
+
const [groupBy, setGroupBy] = (0, import_react2.useState)("none");
|
|
2081
|
+
const [page, setPage] = (0, import_react2.useState)(0);
|
|
2082
|
+
const [expanded, setExpanded] = (0, import_react2.useState)(null);
|
|
2083
|
+
const sessionPrefix = sessionId === void 0 ? "" : sessionId.slice(0, 8);
|
|
2084
|
+
const [onlySession, setOnlySession] = (0, import_react2.useState)(sessionPrefix !== "");
|
|
2085
|
+
const load = (0, import_react2.useCallback)(async () => {
|
|
2086
|
+
setRefreshing(true);
|
|
2087
|
+
try {
|
|
2088
|
+
const next = await readLog();
|
|
2089
|
+
setSnapshot(next);
|
|
2090
|
+
setFailure(void 0);
|
|
2091
|
+
} catch (error) {
|
|
2092
|
+
setFailure(error instanceof Error ? error.message : String(error));
|
|
2093
|
+
} finally {
|
|
2094
|
+
setRefreshing(false);
|
|
2095
|
+
}
|
|
2096
|
+
}, [readLog]);
|
|
2097
|
+
(0, import_react2.useEffect)(() => {
|
|
2098
|
+
void load();
|
|
2099
|
+
}, [load]);
|
|
2100
|
+
const models = (0, import_react2.useMemo)(() => {
|
|
2101
|
+
const ids = /* @__PURE__ */ new Set();
|
|
2102
|
+
for (const entry of snapshot?.entries ?? []) ids.add(entry.model);
|
|
2103
|
+
return [...ids].toSorted();
|
|
2104
|
+
}, [snapshot]);
|
|
2105
|
+
const filtered = (0, import_react2.useMemo)(() => {
|
|
2106
|
+
const query = sessionQuery.trim();
|
|
2107
|
+
return (snapshot?.entries ?? []).filter((entry) => {
|
|
2108
|
+
if (model !== "all" && entry.model !== model) return false;
|
|
2109
|
+
if (result === "ok" && !entry.ok) return false;
|
|
2110
|
+
if (result === "fail" && entry.ok) return false;
|
|
2111
|
+
if (slowOnly && (entry.durationMs ?? 0) < Math.max(0, slowSeconds) * 1e3) return false;
|
|
2112
|
+
if (onlySession && sessionPrefix !== "" && !entry.session.startsWith(sessionPrefix)) return false;
|
|
2113
|
+
if (query !== "" && !entry.session.includes(query)) return false;
|
|
2114
|
+
return true;
|
|
2115
|
+
});
|
|
2116
|
+
}, [snapshot, model, result, slowOnly, slowSeconds, sessionQuery, onlySession, sessionPrefix]);
|
|
2117
|
+
const pages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
|
|
2118
|
+
const safePage = Math.min(page, pages - 1);
|
|
2119
|
+
const pageEntries = filtered.slice(safePage * PAGE_SIZE, (safePage + 1) * PAGE_SIZE);
|
|
2120
|
+
const failures = filtered.filter((entry) => !entry.ok).length;
|
|
2121
|
+
const meanLatency = average(filtered.flatMap((entry) => entry.durationMs === void 0 ? [] : [entry.durationMs]));
|
|
2122
|
+
const meanFirstToken = average(filtered.flatMap((entry) => entry.firstTokenMs === void 0 ? [] : [entry.firstTokenMs]));
|
|
2123
|
+
const meanTps = average(filtered.flatMap((entry) => entry.tps === void 0 ? [] : [entry.tps]));
|
|
2124
|
+
const reuse = snapshot !== void 0 && snapshot.totalRecords > 0 ? Math.max(0, Math.min(1, 1 - snapshot.newConnections / snapshot.totalRecords)) : void 0;
|
|
2125
|
+
const rows = () => {
|
|
2126
|
+
const out = [];
|
|
2127
|
+
let lastGroup;
|
|
2128
|
+
for (const entry of pageEntries) {
|
|
2129
|
+
const group = groupKey(entry, groupBy);
|
|
2130
|
+
if (group !== void 0 && group !== lastGroup) {
|
|
2131
|
+
lastGroup = group;
|
|
2132
|
+
out.push(
|
|
2133
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { className: request_log_default.group, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { colSpan: 10, children: group }) }, `group-${group}-${entry.seq}`)
|
|
2134
|
+
);
|
|
2135
|
+
}
|
|
2136
|
+
const state = !entry.ok ? "rowFail" : entry.tps !== void 0 && entry.tps < 5 ? "rowSlow" : "rowOk";
|
|
2137
|
+
out.push(
|
|
2138
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
2139
|
+
"tr",
|
|
2140
|
+
{
|
|
2141
|
+
className: `${request_log_default.row} ${request_log_default[state]}`,
|
|
2142
|
+
onClick: () => {
|
|
2143
|
+
setExpanded(expanded === entry.seq ? null : entry.seq);
|
|
2144
|
+
},
|
|
2145
|
+
children: [
|
|
2146
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: new Date(entry.atMs).toLocaleTimeString(getLocale(), { hour12: false }) }),
|
|
2147
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { className: request_log_default.mono, children: entry.model }),
|
|
2148
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { className: request_log_default.mono, children: entry.session === "" ? "\u2014" : entry.session }),
|
|
2149
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: count2(entry.inputTokens) }),
|
|
2150
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: count2(entry.outputTokens) }),
|
|
2151
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: count2(entry.cacheReadTokens) }),
|
|
2152
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: rate2(entry.tps) }),
|
|
2153
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: duration(entry.firstTokenMs) }),
|
|
2154
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: duration(entry.durationMs) }),
|
|
2155
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: entry.ok ? entry.status === void 0 ? "\u2713" : String(entry.status) : entry.code ?? "\u2717" })
|
|
2156
|
+
]
|
|
2157
|
+
},
|
|
2158
|
+
entry.seq
|
|
2159
|
+
)
|
|
2160
|
+
);
|
|
2161
|
+
if (expanded === entry.seq) {
|
|
2162
|
+
out.push(
|
|
2163
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { className: request_log_default.detail, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { colSpan: 10, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.detailGrid, children: [
|
|
2164
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.detailItem, children: [
|
|
2165
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.detailLabel, children: t("requestLogDetailMethod") }),
|
|
2166
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `${request_log_default.detailValue} ${request_log_default.mono}`, children: entry.method })
|
|
2167
|
+
] }),
|
|
2168
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.detailItem, children: [
|
|
2169
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.detailLabel, children: t("requestLogDetailUrl") }),
|
|
2170
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `${request_log_default.detailValue} ${request_log_default.mono}`, children: entry.url })
|
|
2171
|
+
] }),
|
|
2172
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.detailItem, children: [
|
|
2173
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.detailLabel, children: t("requestLogDetailSession") }),
|
|
2174
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `${request_log_default.detailValue} ${request_log_default.mono}`, children: entry.session === "" ? "\u2014" : entry.session })
|
|
2175
|
+
] }),
|
|
2176
|
+
entry.poolKey !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.detailItem, children: [
|
|
2177
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.detailLabel, children: t("requestLogDetailPool") }),
|
|
2178
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `${request_log_default.detailValue} ${request_log_default.mono}`, children: entry.poolKey })
|
|
2179
|
+
] }),
|
|
2180
|
+
entry.headers !== void 0 && (entry.headers.session !== void 0 || entry.headers.userAgent !== void 0) && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.detailItem, children: [
|
|
2181
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.detailLabel, children: t("requestLogDetailUserAgent") }),
|
|
2182
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `${request_log_default.detailValue} ${request_log_default.mono}`, children: [entry.headers.session, entry.headers.userAgent].filter((part) => part !== void 0).join(" \xB7 ") })
|
|
2183
|
+
] }),
|
|
2184
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.detailItem, children: [
|
|
2185
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.detailLabel, children: t("requestLogDetailShape") }),
|
|
2186
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: request_log_default.detailValue, children: [
|
|
2187
|
+
`${entry.shape?.messages ?? 0} ${t("requestLogDetailMessages")}`,
|
|
2188
|
+
entry.shape !== void 0 && entry.shape.tools > 0 && ` \xB7 ${entry.shape.tools} ${t("requestLogDetailTools")}`,
|
|
2189
|
+
entry.shape?.hasImage === true && ` \xB7 ${t("requestLogDetailHasImage")}`
|
|
2190
|
+
] })
|
|
2191
|
+
] }),
|
|
2192
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.detailItem, children: [
|
|
2193
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.detailLabel, children: t("requestLogDetailTokens") }),
|
|
2194
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.detailValue, children: `${count2(entry.inputTokens)} / ${count2(entry.outputTokens)} / ${count2(entry.cacheReadTokens)}` })
|
|
2195
|
+
] }),
|
|
2196
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.detailItem, children: [
|
|
2197
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.detailLabel, children: t("requestLogColTps") }),
|
|
2198
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.detailValue, children: rate2(entry.tps) })
|
|
2199
|
+
] }),
|
|
2200
|
+
!entry.ok && entry.code !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.detailItem, children: [
|
|
2201
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.detailLabel, children: t("requestLogDetailError") }),
|
|
2202
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.detailValue, children: entry.code })
|
|
2203
|
+
] })
|
|
2204
|
+
] }) }) }, `detail-${entry.seq}`)
|
|
2205
|
+
);
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2208
|
+
return out;
|
|
2209
|
+
};
|
|
2210
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.page, children: [
|
|
2211
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.head, children: [
|
|
2212
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.headText, children: [
|
|
2213
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h1", { className: request_log_default.title, children: t("requestLogTitle") }),
|
|
2214
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: request_log_default.subtitle, children: t("requestLogPageHint") })
|
|
2215
|
+
] }),
|
|
2216
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: request_log_default.headActions, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { type: "button", className: request_log_default.button, onClick: () => {
|
|
2217
|
+
void load();
|
|
2218
|
+
}, disabled: refreshing, children: [
|
|
2219
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives.IconRefreshOutlineRegular, { size: 13 }),
|
|
2220
|
+
t("requestLogRefresh")
|
|
2221
|
+
] }) })
|
|
2222
|
+
] }),
|
|
2223
|
+
!enabled() && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: request_log_default.notice, children: t("requestLogDisabled") }),
|
|
2224
|
+
failure !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: `${request_log_default.notice} ${request_log_default.noticeError}`, children: failure }),
|
|
2225
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.summary, children: [
|
|
2226
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.card, children: [
|
|
2227
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.cardLabel, children: t("requestLogStatRequests") }),
|
|
2228
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.cardValue, children: filtered.length.toLocaleString(getLocale()) })
|
|
2229
|
+
] }),
|
|
2230
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `${request_log_default.card} ${failures > 0 ? request_log_default.cardError : ""}`, children: [
|
|
2231
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.cardLabel, children: t("requestLogStatFailures") }),
|
|
2232
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.cardValue, children: failures.toLocaleString(getLocale()) })
|
|
2233
|
+
] }),
|
|
2234
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.card, children: [
|
|
2235
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.cardLabel, children: t("requestLogStatLatency") }),
|
|
2236
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.cardValue, children: duration(meanLatency) })
|
|
2237
|
+
] }),
|
|
2238
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.card, children: [
|
|
2239
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.cardLabel, children: t("requestLogStatFirstToken") }),
|
|
2240
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.cardValue, children: duration(meanFirstToken) })
|
|
2241
|
+
] }),
|
|
2242
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.card, children: [
|
|
2243
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.cardLabel, children: t("requestLogStatTps") }),
|
|
2244
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.cardValue, children: rate2(meanTps) })
|
|
2245
|
+
] }),
|
|
2246
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.card, children: [
|
|
2247
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.cardLabel, children: t("requestLogReuse") }),
|
|
2248
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.cardValue, children: reuse === void 0 ? "\u2014" : `${(reuse * 100).toFixed(0)}%` })
|
|
2249
|
+
] })
|
|
2250
|
+
] }),
|
|
2251
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.toolbar, children: [
|
|
2252
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: request_log_default.field, children: [
|
|
2253
|
+
t("requestLogFilterModel"),
|
|
2254
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
2255
|
+
"select",
|
|
2256
|
+
{
|
|
2257
|
+
className: request_log_default.select,
|
|
2258
|
+
value: model,
|
|
2259
|
+
onChange: (event) => {
|
|
2260
|
+
setModel(event.target.value);
|
|
2261
|
+
setPage(0);
|
|
2262
|
+
},
|
|
2263
|
+
children: [
|
|
2264
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "all", children: t("requestLogFilterModelAll") }),
|
|
2265
|
+
models.map((id4) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: id4, children: id4 }, id4))
|
|
2266
|
+
]
|
|
2267
|
+
}
|
|
2268
|
+
)
|
|
2269
|
+
] }),
|
|
2270
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: request_log_default.field, children: [
|
|
2271
|
+
t("requestLogFilterResult"),
|
|
2272
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
2273
|
+
"select",
|
|
2274
|
+
{
|
|
2275
|
+
className: request_log_default.select,
|
|
2276
|
+
value: result,
|
|
2277
|
+
onChange: (event) => {
|
|
2278
|
+
setResult(event.target.value);
|
|
2279
|
+
setPage(0);
|
|
2280
|
+
},
|
|
2281
|
+
children: [
|
|
2282
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "all", children: t("requestLogResultAll") }),
|
|
2283
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "ok", children: t("requestLogResultOk") }),
|
|
2284
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "fail", children: t("requestLogResultFail") })
|
|
2285
|
+
]
|
|
2286
|
+
}
|
|
2287
|
+
)
|
|
2288
|
+
] }),
|
|
2289
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: request_log_default.field, children: [
|
|
2290
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2291
|
+
"input",
|
|
2292
|
+
{
|
|
2293
|
+
className: request_log_default.checkbox,
|
|
2294
|
+
type: "checkbox",
|
|
2295
|
+
checked: slowOnly,
|
|
2296
|
+
onChange: (event) => {
|
|
2297
|
+
setSlowOnly(event.target.checked);
|
|
2298
|
+
setPage(0);
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
),
|
|
2302
|
+
t("requestLogSlowOnly"),
|
|
2303
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2304
|
+
"input",
|
|
2305
|
+
{
|
|
2306
|
+
className: `${request_log_default.input} ${request_log_default.inputNumber}`,
|
|
2307
|
+
type: "number",
|
|
2308
|
+
min: 1,
|
|
2309
|
+
value: slowSeconds,
|
|
2310
|
+
disabled: !slowOnly,
|
|
2311
|
+
"aria-label": t("requestLogSlowSeconds"),
|
|
2312
|
+
onChange: (event) => {
|
|
2313
|
+
setSlowSeconds(Number(event.target.value));
|
|
2314
|
+
setPage(0);
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
),
|
|
2318
|
+
t("requestLogSlowSeconds")
|
|
2319
|
+
] }),
|
|
2320
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: request_log_default.field, children: [
|
|
2321
|
+
t("requestLogFilterSession"),
|
|
2322
|
+
sessionPrefix !== "" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
2323
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2324
|
+
"input",
|
|
2325
|
+
{
|
|
2326
|
+
className: request_log_default.checkbox,
|
|
2327
|
+
type: "checkbox",
|
|
2328
|
+
checked: onlySession,
|
|
2329
|
+
onChange: (event) => {
|
|
2330
|
+
setOnlySession(event.target.checked);
|
|
2331
|
+
setPage(0);
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
),
|
|
2335
|
+
t("requestLogOnlySession")
|
|
2336
|
+
] }),
|
|
2337
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2338
|
+
"input",
|
|
2339
|
+
{
|
|
2340
|
+
className: request_log_default.input,
|
|
2341
|
+
type: "search",
|
|
2342
|
+
value: sessionQuery,
|
|
2343
|
+
disabled: onlySession,
|
|
2344
|
+
onChange: (event) => {
|
|
2345
|
+
setSessionQuery(event.target.value);
|
|
2346
|
+
setPage(0);
|
|
2347
|
+
}
|
|
2348
|
+
}
|
|
2349
|
+
)
|
|
2350
|
+
] }),
|
|
2351
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: request_log_default.field, children: [
|
|
2352
|
+
t("requestLogGroupBy"),
|
|
2353
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
2354
|
+
"select",
|
|
2355
|
+
{
|
|
2356
|
+
className: request_log_default.select,
|
|
2357
|
+
value: groupBy,
|
|
2358
|
+
onChange: (event) => {
|
|
2359
|
+
setGroupBy(event.target.value);
|
|
2360
|
+
setPage(0);
|
|
2361
|
+
},
|
|
2362
|
+
children: [
|
|
2363
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "none", children: t("requestLogGroupNone") }),
|
|
2364
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "session", children: t("requestLogGroupSession") }),
|
|
2365
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "model", children: t("requestLogGroupModel") }),
|
|
2366
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "result", children: t("requestLogGroupResult") })
|
|
2367
|
+
]
|
|
2368
|
+
}
|
|
2369
|
+
)
|
|
2370
|
+
] })
|
|
2371
|
+
] }),
|
|
2372
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: request_log_default.tableWrap, children: filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: request_log_default.empty, children: t("requestLogEmpty") }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("table", { className: request_log_default.table, children: [
|
|
2373
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("tr", { children: [
|
|
2374
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { children: t("requestLogColTime") }),
|
|
2375
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { children: t("requestLogColModel") }),
|
|
2376
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { children: t("requestLogColSession") }),
|
|
2377
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { children: t("requestLogColIn") }),
|
|
2378
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { children: t("requestLogColOut") }),
|
|
2379
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { children: t("requestLogColCache") }),
|
|
2380
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { children: t("requestLogColTps") }),
|
|
2381
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { children: t("requestLogColFirstToken") }),
|
|
2382
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { children: t("requestLogColLatency") }),
|
|
2383
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { children: t("requestLogColStatus") })
|
|
2384
|
+
] }) }),
|
|
2385
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tbody", { children: rows() })
|
|
2386
|
+
] }) }),
|
|
2387
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.foot, children: [
|
|
2388
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: `${filtered.length.toLocaleString(getLocale())} / ${(snapshot?.totalRecords ?? 0).toLocaleString(getLocale())} ${t("requestLogStatRequests")}` }),
|
|
2389
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.pager, children: [
|
|
2390
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: request_log_default.button, disabled: safePage <= 0, onClick: () => {
|
|
2391
|
+
setPage(safePage - 1);
|
|
2392
|
+
}, children: t("requestLogPagePrev") }),
|
|
2393
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: `${safePage + 1} ${t("requestLogPageOf")} ${pages}` }),
|
|
2394
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: request_log_default.button, disabled: safePage >= pages - 1, onClick: () => {
|
|
2395
|
+
setPage(safePage + 1);
|
|
2396
|
+
}, children: t("requestLogPageNext") })
|
|
2397
|
+
] })
|
|
2398
|
+
] })
|
|
2399
|
+
] });
|
|
2400
|
+
}
|
|
2401
|
+
|
|
2402
|
+
// src/client/RequestLogPanelIcon.tsx
|
|
2403
|
+
var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
2404
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
2405
|
+
function RequestLogPanelIcon({ size }) {
|
|
2406
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives2.IconDataOutlineRegular, { size });
|
|
2407
|
+
}
|
|
2408
|
+
|
|
2409
|
+
// src/client/UsagePill.tsx
|
|
2410
|
+
var import_react3 = require("react");
|
|
2411
|
+
|
|
2412
|
+
// plugin-css:/home/runner/work/dshopencodego/dshopencodego/src/client/pill.module.css
|
|
2413
|
+
var id3 = "@dan-ai-studio/dshopencodego/pill.module.css";
|
|
2414
|
+
if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id3) + "]")) {
|
|
2415
|
+
const style = document.createElement("style");
|
|
2416
|
+
style.dataset.plugin = "@dan-ai-studio/dshopencodego";
|
|
2417
|
+
style.dataset.pluginCss = id3;
|
|
1670
2418
|
style.textContent = ".mMNkkW_root{align-items:center;display:inline-flex;position:relative}.mMNkkW_trigger{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;white-space:nowrap;border-radius:999px;padding:.35rem .6rem;font-size:.8rem;line-height:1}.mMNkkW_trigger:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l2)}.mMNkkW_panel{z-index:20;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-overlay);width:18rem;color:var(--dsw-alias-label-primary);border-radius:.6rem;flex-direction:column;gap:.6rem;padding:.75rem .85rem;display:flex;position:absolute;bottom:calc(100% + .5rem);right:0;box-shadow:0 8px 24px #0000002e}.mMNkkW_window{flex-direction:column;gap:.25rem;display:flex}.mMNkkW_row{justify-content:space-between;gap:.5rem;font-size:.85rem;display:flex}.mMNkkW_hint{color:var(--dsw-alias-label-secondary);margin:0;font-size:.75rem}.mMNkkW_progress{width:100%;height:.35rem;accent-color:var(--dsw-alias-brand-primary)}.mMNkkW_limited{color:var(--dsw-alias-state-warn-primary);font-size:.75rem}.mMNkkW_warning{border:1px solid var(--dsw-alias-state-warn-primary);color:var(--dsw-alias-label-primary);border-radius:.4rem;padding:.4rem .5rem;font-size:.75rem}.mMNkkW_retry{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;border-radius:.35rem;align-self:flex-start;padding:.25rem .5rem;font-size:.75rem}.mMNkkW_local{border-top:1px solid var(--dsw-alias-border-l1);flex-direction:column;gap:.2rem;padding-top:.5rem;display:flex}";
|
|
1671
2419
|
document.head.appendChild(style);
|
|
1672
2420
|
}
|
|
1673
2421
|
var pill_default = { "hint": "mMNkkW_hint", "limited": "mMNkkW_limited", "local": "mMNkkW_local", "panel": "mMNkkW_panel", "progress": "mMNkkW_progress", "retry": "mMNkkW_retry", "root": "mMNkkW_root", "row": "mMNkkW_row", "trigger": "mMNkkW_trigger", "warning": "mMNkkW_warning", "window": "mMNkkW_window" };
|
|
1674
2422
|
|
|
1675
2423
|
// src/client/UsagePill.tsx
|
|
1676
|
-
var
|
|
2424
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1677
2425
|
function failureOf(error) {
|
|
1678
2426
|
if (error !== null && typeof error === "object" && "code" in error && error.code === "dshopencodego/usage-unavailable") {
|
|
1679
2427
|
const details = error.details;
|
|
@@ -1694,8 +2442,8 @@ function formatUSD(value) {
|
|
|
1694
2442
|
return value < 1 ? `$${value.toFixed(4)}` : `$${value.toFixed(2)}`;
|
|
1695
2443
|
}
|
|
1696
2444
|
function UsagePill({ directory, ...rest }) {
|
|
1697
|
-
const state = (0,
|
|
1698
|
-
return state.current?.provider === "opencode-go" ? /* @__PURE__ */ (0,
|
|
2445
|
+
const state = (0, import_react3.useSyncExternalStore)(directory.subscribe, directory.getSnapshot, directory.getSnapshot);
|
|
2446
|
+
return state.current?.provider === "opencode-go" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ActiveUsage, { ...rest }) : null;
|
|
1699
2447
|
}
|
|
1700
2448
|
function ActiveUsage({
|
|
1701
2449
|
readWindows,
|
|
@@ -1703,14 +2451,14 @@ function ActiveUsage({
|
|
|
1703
2451
|
t,
|
|
1704
2452
|
getLocale
|
|
1705
2453
|
}) {
|
|
1706
|
-
const [windows, setWindows] = (0,
|
|
1707
|
-
const [meter, setMeter] = (0,
|
|
1708
|
-
const [failure, setFailure] = (0,
|
|
1709
|
-
const [updatedAt, setUpdatedAt] = (0,
|
|
1710
|
-
const [refreshing, setRefreshing] = (0,
|
|
1711
|
-
const [open, setOpen] = (0,
|
|
1712
|
-
const root = (0,
|
|
1713
|
-
const refresh = (0,
|
|
2454
|
+
const [windows, setWindows] = (0, import_react3.useState)(void 0);
|
|
2455
|
+
const [meter, setMeter] = (0, import_react3.useState)(void 0);
|
|
2456
|
+
const [failure, setFailure] = (0, import_react3.useState)(void 0);
|
|
2457
|
+
const [updatedAt, setUpdatedAt] = (0, import_react3.useState)(void 0);
|
|
2458
|
+
const [refreshing, setRefreshing] = (0, import_react3.useState)(false);
|
|
2459
|
+
const [open, setOpen] = (0, import_react3.useState)(false);
|
|
2460
|
+
const root = (0, import_react3.useRef)(null);
|
|
2461
|
+
const refresh = (0, import_react3.useCallback)(async () => {
|
|
1714
2462
|
setRefreshing(true);
|
|
1715
2463
|
try {
|
|
1716
2464
|
const [nextWindows, nextMeter] = await Promise.all([readWindows(), readMeter()]);
|
|
@@ -1729,7 +2477,7 @@ function ActiveUsage({
|
|
|
1729
2477
|
setRefreshing(false);
|
|
1730
2478
|
}
|
|
1731
2479
|
}, [readWindows, readMeter]);
|
|
1732
|
-
(0,
|
|
2480
|
+
(0, import_react3.useEffect)(() => {
|
|
1733
2481
|
let alive = true;
|
|
1734
2482
|
const run = () => {
|
|
1735
2483
|
if (!alive || document.visibilityState === "hidden") return;
|
|
@@ -1744,7 +2492,7 @@ function ActiveUsage({
|
|
|
1744
2492
|
document.removeEventListener("visibilitychange", run);
|
|
1745
2493
|
};
|
|
1746
2494
|
}, [refresh]);
|
|
1747
|
-
(0,
|
|
2495
|
+
(0, import_react3.useEffect)(() => {
|
|
1748
2496
|
if (!open) return;
|
|
1749
2497
|
const close = (event) => {
|
|
1750
2498
|
if (!root.current?.contains(event.target)) setOpen(false);
|
|
@@ -1762,8 +2510,8 @@ function ActiveUsage({
|
|
|
1762
2510
|
const label = windows === void 0 ? `Go \xB7 ${failure === void 0 ? "\u2026" : t("usageUnavailable")}` : `Go \xB7 ${t("usageRolling")} ${windows.rolling.percent}% \xB7 ${t("usageWeekly")} ${windows.weekly.percent}%` + (failure === void 0 ? "" : ` \xB7 ${t("usageStale")}`);
|
|
1763
2511
|
const unpriced = (meter?.models ?? []).filter((entry) => entry.estimatedUSD === void 0);
|
|
1764
2512
|
const unpricedModels = unpriced.slice(0, MAX_UNPRICED_IDS).map((entry) => entry.model).join(", ") + (unpriced.length > MAX_UNPRICED_IDS ? ` +${unpriced.length - MAX_UNPRICED_IDS}` : "");
|
|
1765
|
-
return /* @__PURE__ */ (0,
|
|
1766
|
-
/* @__PURE__ */ (0,
|
|
2513
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: pill_default.root, ref: root, children: [
|
|
2514
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1767
2515
|
"button",
|
|
1768
2516
|
{
|
|
1769
2517
|
type: "button",
|
|
@@ -1777,71 +2525,71 @@ function ActiveUsage({
|
|
|
1777
2525
|
children: label
|
|
1778
2526
|
}
|
|
1779
2527
|
),
|
|
1780
|
-
open && /* @__PURE__ */ (0,
|
|
1781
|
-
/* @__PURE__ */ (0,
|
|
1782
|
-
failure !== void 0 && /* @__PURE__ */ (0,
|
|
1783
|
-
/* @__PURE__ */ (0,
|
|
1784
|
-
failure.message.length > 0 && /* @__PURE__ */ (0,
|
|
1785
|
-
windows !== void 0 && /* @__PURE__ */ (0,
|
|
2528
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: pill_default.panel, role: "dialog", "aria-label": t("usageTitle"), "aria-busy": refreshing, children: [
|
|
2529
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: t("usageTitle") }),
|
|
2530
|
+
failure !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: pill_default.warning, role: "alert", children: [
|
|
2531
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: t("usageUnavailable") }) }),
|
|
2532
|
+
failure.message.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { children: failure.message }),
|
|
2533
|
+
windows !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { children: t("usageStale") })
|
|
1786
2534
|
] }),
|
|
1787
|
-
windows === void 0 && failure === void 0 && /* @__PURE__ */ (0,
|
|
1788
|
-
windows !== void 0 && [["rolling", "usageRolling"], ["weekly", "usageWeekly"], ["monthly", "usageMonthly"]].map(([key, label2]) => /* @__PURE__ */ (0,
|
|
1789
|
-
/* @__PURE__ */ (0,
|
|
1790
|
-
/* @__PURE__ */ (0,
|
|
1791
|
-
/* @__PURE__ */ (0,
|
|
2535
|
+
windows === void 0 && failure === void 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: pill_default.hint, children: t("usageLoading") }),
|
|
2536
|
+
windows !== void 0 && [["rolling", "usageRolling"], ["weekly", "usageWeekly"], ["monthly", "usageMonthly"]].map(([key, label2]) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: pill_default.window, children: [
|
|
2537
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: pill_default.row, children: [
|
|
2538
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: t(label2) }),
|
|
2539
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("strong", { children: [
|
|
1792
2540
|
windows[key].percent,
|
|
1793
2541
|
"%"
|
|
1794
2542
|
] })
|
|
1795
2543
|
] }),
|
|
1796
|
-
/* @__PURE__ */ (0,
|
|
1797
|
-
/* @__PURE__ */ (0,
|
|
2544
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("progress", { className: pill_default.progress, max: 100, value: Math.min(100, windows[key].percent), "aria-label": t(label2) }),
|
|
2545
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: pill_default.hint, children: [
|
|
1798
2546
|
t("usageResets"),
|
|
1799
2547
|
" ",
|
|
1800
2548
|
new Date(windows[key].resetsAt).toLocaleString(getLocale?.())
|
|
1801
2549
|
] }),
|
|
1802
|
-
windows[key].status === "rate-limited" && /* @__PURE__ */ (0,
|
|
2550
|
+
windows[key].status === "rate-limited" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: pill_default.limited, children: t("usageLimited") })
|
|
1803
2551
|
] }, key)),
|
|
1804
|
-
meter !== void 0 && /* @__PURE__ */ (0,
|
|
1805
|
-
/* @__PURE__ */ (0,
|
|
1806
|
-
/* @__PURE__ */ (0,
|
|
1807
|
-
/* @__PURE__ */ (0,
|
|
1808
|
-
/* @__PURE__ */ (0,
|
|
2552
|
+
meter !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: pill_default.local, children: [
|
|
2553
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: t("usageSinceBoot") }),
|
|
2554
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: pill_default.row, children: [
|
|
2555
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: t("usageCallsUnit") }),
|
|
2556
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: meter.totals.calls })
|
|
1809
2557
|
] }),
|
|
1810
|
-
/* @__PURE__ */ (0,
|
|
1811
|
-
/* @__PURE__ */ (0,
|
|
1812
|
-
/* @__PURE__ */ (0,
|
|
2558
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: pill_default.row, children: [
|
|
2559
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: t("usageTokensUnit") }),
|
|
2560
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: meter.totals.totalTokens.toLocaleString(getLocale?.()) })
|
|
1813
2561
|
] }),
|
|
1814
|
-
/* @__PURE__ */ (0,
|
|
1815
|
-
/* @__PURE__ */ (0,
|
|
1816
|
-
/* @__PURE__ */ (0,
|
|
2562
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: pill_default.row, children: [
|
|
2563
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: t("usageCached") }),
|
|
2564
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: meter.totals.cacheReadTokens.toLocaleString(getLocale?.()) })
|
|
1817
2565
|
] }),
|
|
1818
|
-
meter.totals.reasoningTokens !== void 0 && /* @__PURE__ */ (0,
|
|
1819
|
-
/* @__PURE__ */ (0,
|
|
1820
|
-
/* @__PURE__ */ (0,
|
|
2566
|
+
meter.totals.reasoningTokens !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: pill_default.row, children: [
|
|
2567
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: t("usageReasoning") }),
|
|
2568
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: meter.totals.reasoningTokens.toLocaleString(getLocale?.()) })
|
|
1821
2569
|
] }),
|
|
1822
|
-
/* @__PURE__ */ (0,
|
|
1823
|
-
/* @__PURE__ */ (0,
|
|
1824
|
-
/* @__PURE__ */ (0,
|
|
2570
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: pill_default.row, children: [
|
|
2571
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: t("usageSpend") }),
|
|
2572
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: meter.totals.estimatedUSD === void 0 ? t("usageUnpriced") : formatUSD(meter.totals.estimatedUSD) })
|
|
1825
2573
|
] }),
|
|
1826
|
-
meter.totals.unpricedTokens !== void 0 && /* @__PURE__ */ (0,
|
|
2574
|
+
meter.totals.unpricedTokens !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: pill_default.hint, children: [
|
|
1827
2575
|
t("usageSpendPartial"),
|
|
1828
2576
|
" ",
|
|
1829
2577
|
meter.totals.unpricedTokens.toLocaleString(getLocale?.())
|
|
1830
2578
|
] }),
|
|
1831
|
-
unpriced.length > 0 && /* @__PURE__ */ (0,
|
|
2579
|
+
unpriced.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: pill_default.hint, children: [
|
|
1832
2580
|
t("usageUnpricedModels"),
|
|
1833
2581
|
" ",
|
|
1834
2582
|
unpricedModels
|
|
1835
2583
|
] }),
|
|
1836
|
-
/* @__PURE__ */ (0,
|
|
1837
|
-
/* @__PURE__ */ (0,
|
|
2584
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: pill_default.hint, children: t("usageSpendHint") }),
|
|
2585
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: pill_default.hint, children: t("usageLocalHint") })
|
|
1838
2586
|
] }),
|
|
1839
|
-
updatedAt !== void 0 && /* @__PURE__ */ (0,
|
|
2587
|
+
updatedAt !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: pill_default.hint, children: [
|
|
1840
2588
|
t("usageLastUpdated"),
|
|
1841
2589
|
" ",
|
|
1842
2590
|
new Date(updatedAt).toLocaleString(getLocale?.())
|
|
1843
2591
|
] }),
|
|
1844
|
-
/* @__PURE__ */ (0,
|
|
2592
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: pill_default.retry, disabled: refreshing, onClick: () => {
|
|
1845
2593
|
void refresh();
|
|
1846
2594
|
}, children: t(refreshing ? "usageRefreshing" : "usageRetry") })
|
|
1847
2595
|
] })
|
|
@@ -1850,6 +2598,7 @@ function ActiveUsage({
|
|
|
1850
2598
|
|
|
1851
2599
|
// src/client/index.ts
|
|
1852
2600
|
var NS = "settings.dshopencodego";
|
|
2601
|
+
var REQUEST_LOG_PANEL = "dshopencodego-request-log";
|
|
1853
2602
|
var inject = ["slots", "locale", "remote"];
|
|
1854
2603
|
function apply(ctx) {
|
|
1855
2604
|
ctx.effect(() => ctx.locale.register(NS, { zh, en }), "dshopencodego: copy dictionaries");
|
|
@@ -1859,7 +2608,8 @@ function apply(ctx) {
|
|
|
1859
2608
|
...usageRemote.descriptors,
|
|
1860
2609
|
...catalogRemote.descriptors,
|
|
1861
2610
|
...updateRemote.descriptors,
|
|
1862
|
-
...networkRemote.descriptors
|
|
2611
|
+
...networkRemote.descriptors,
|
|
2612
|
+
...requestLogRemote.descriptors
|
|
1863
2613
|
]
|
|
1864
2614
|
});
|
|
1865
2615
|
ctx.effect(() => {
|
|
@@ -1872,13 +2622,14 @@ function apply(ctx) {
|
|
|
1872
2622
|
void dispose?.();
|
|
1873
2623
|
};
|
|
1874
2624
|
}, "dshopencodego: usage Remote");
|
|
1875
|
-
ctx.inject(["configForms", "remote.opencodeGoCatalog", "remote.opencodeGoUpdate", "remote.opencodeGoNetwork", "remote.credentials"], (scope) => {
|
|
2625
|
+
ctx.inject(["configForms", "remote.opencodeGoCatalog", "remote.opencodeGoUpdate", "remote.opencodeGoNetwork", "remote.opencodeGoRequestLog", "remote.credentials"], (scope) => {
|
|
1876
2626
|
const forms = scope.get("configForms");
|
|
1877
2627
|
const pluginManager = {};
|
|
2628
|
+
const profile = forms?.get("dshopencodego");
|
|
1878
2629
|
const controller = new SectionController({
|
|
1879
2630
|
remote: scope.remote,
|
|
1880
2631
|
pluginManager,
|
|
1881
|
-
scope:
|
|
2632
|
+
scope: profile
|
|
1882
2633
|
});
|
|
1883
2634
|
scope.inject(["remote.pluginManager"], (managerScope) => {
|
|
1884
2635
|
pluginManager.current = managerScope.remote.pluginManager;
|
|
@@ -1890,6 +2641,47 @@ function apply(ctx) {
|
|
|
1890
2641
|
scope.effect(() => () => {
|
|
1891
2642
|
controller.dispose();
|
|
1892
2643
|
});
|
|
2644
|
+
const requestLog = {
|
|
2645
|
+
readLog: async () => {
|
|
2646
|
+
const result = await scope.remote.opencodeGoRequestLog.readLog();
|
|
2647
|
+
if (!result.ok) throw result.error;
|
|
2648
|
+
return result.value;
|
|
2649
|
+
},
|
|
2650
|
+
// Read live: the switch on the settings page can change while the log
|
|
2651
|
+
// page sits open, and the page says so rather than pretending.
|
|
2652
|
+
enabled: () => {
|
|
2653
|
+
const value = profile?.getSnapshot().value;
|
|
2654
|
+
if (value === null || typeof value !== "object") return false;
|
|
2655
|
+
return value.requestLogEnabled === true;
|
|
2656
|
+
},
|
|
2657
|
+
t: (key) => translate(key),
|
|
2658
|
+
getLocale: () => scope.locale.getLocale().active
|
|
2659
|
+
};
|
|
2660
|
+
scope.slots.inject("main", function* () {
|
|
2661
|
+
yield scope.slots.register({
|
|
2662
|
+
name: "main",
|
|
2663
|
+
key: REQUEST_LOG_PANEL,
|
|
2664
|
+
locale: NS,
|
|
2665
|
+
inject: () => requestLog
|
|
2666
|
+
}, RequestLogPage);
|
|
2667
|
+
});
|
|
2668
|
+
scope.slots.inject("sidebar.panellist", () => scope.slots.register({
|
|
2669
|
+
name: "sidebar.panellist",
|
|
2670
|
+
id: REQUEST_LOG_PANEL,
|
|
2671
|
+
// After the Host's own panels, which run from 0.
|
|
2672
|
+
order: 100,
|
|
2673
|
+
label: () => translate("requestLogTitle"),
|
|
2674
|
+
locale: NS
|
|
2675
|
+
}, RequestLogPanelIcon));
|
|
2676
|
+
scope.slots.inject("conversation.view", () => scope.slots.register({
|
|
2677
|
+
name: "conversation.view",
|
|
2678
|
+
id: "dshopencodego-request-log",
|
|
2679
|
+
// After the Host's own View (the chat itself), which runs at 0.
|
|
2680
|
+
order: 100,
|
|
2681
|
+
label: () => translate("requestLogTitle"),
|
|
2682
|
+
locale: NS,
|
|
2683
|
+
inject: (sessionId) => ({ ...requestLog, sessionId: String(sessionId) })
|
|
2684
|
+
}, RequestLogPage));
|
|
1893
2685
|
scope.slots.inject("settings.section", () => scope.slots.register({
|
|
1894
2686
|
name: "settings.section",
|
|
1895
2687
|
id: "dshopencodego",
|
|
@@ -1902,7 +2694,16 @@ function apply(ctx) {
|
|
|
1902
2694
|
inject: () => ({
|
|
1903
2695
|
controller,
|
|
1904
2696
|
t: (key) => translate(key),
|
|
1905
|
-
getLocale: () => scope.locale.getLocale().active
|
|
2697
|
+
getLocale: () => scope.locale.getLocale().active,
|
|
2698
|
+
// The settings page opens the log in the main column, beside this
|
|
2699
|
+
// page rather than over it. A composition without the layout service
|
|
2700
|
+
// has no main column to select, so the button does nothing there.
|
|
2701
|
+
openRequestLog: () => {
|
|
2702
|
+
try {
|
|
2703
|
+
ctx.layout.selectPanel(REQUEST_LOG_PANEL);
|
|
2704
|
+
} catch {
|
|
2705
|
+
}
|
|
2706
|
+
}
|
|
1906
2707
|
})
|
|
1907
2708
|
}, Section));
|
|
1908
2709
|
});
|