kanna-code 0.26.7 → 0.26.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <link rel="icon" type="image/png" href="/favicon.png" />
7
7
  <title>Kanna</title>
8
- <script type="module" crossorigin src="/assets/index-CH3ZbXse.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-BaucHYoH.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="/assets/index-C5RBxQW4.css">
10
10
  </head>
11
11
  <body>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kanna-code",
3
3
  "type": "module",
4
- "version": "0.26.7",
4
+ "version": "0.26.8",
5
5
  "description": "A beautiful web UI for Claude Code",
6
6
  "license": "MIT",
7
7
  "keywords": [
@@ -19,6 +19,22 @@ import { resolveLocalPath } from "./paths"
19
19
 
20
20
  const COMPACTION_THRESHOLD_BYTES = 2 * 1024 * 1024
21
21
  const STALE_EMPTY_CHAT_MAX_AGE_MS = 30 * 60 * 1000
22
+
23
+ function isSendToStartingProfilingEnabled() {
24
+ return process.env.KANNA_PROFILE_SEND_TO_STARTING === "1"
25
+ }
26
+
27
+ function logSendToStartingProfile(stage: string, details?: Record<string, unknown>) {
28
+ if (!isSendToStartingProfilingEnabled()) {
29
+ return
30
+ }
31
+
32
+ console.log("[kanna/send->starting][server]", JSON.stringify({
33
+ stage,
34
+ ...details,
35
+ }))
36
+ }
37
+
22
38
  interface LegacyTranscriptStats {
23
39
  hasLegacyData: boolean
24
40
  sources: Array<"snapshot" | "messages_log">
@@ -589,13 +605,27 @@ export class EventStore {
589
605
  this.requireChat(chatId)
590
606
  const payload = `${JSON.stringify(entry)}\n`
591
607
  const transcriptPath = this.transcriptPath(chatId)
608
+ const queuedAt = performance.now()
592
609
  this.writeChain = this.writeChain.then(async () => {
610
+ const startedAt = performance.now()
611
+ const queueDelayMs = Number((startedAt - queuedAt).toFixed(1))
593
612
  await mkdir(this.transcriptsDir, { recursive: true })
613
+ const beforeAppendAt = performance.now()
594
614
  await appendFile(transcriptPath, payload, "utf8")
615
+ const afterAppendAt = performance.now()
595
616
  this.applyMessageMetadata(chatId, entry)
596
617
  if (this.cachedTranscript?.chatId === chatId) {
597
618
  this.cachedTranscript.entries.push({ ...entry })
598
619
  }
620
+ logSendToStartingProfile("event_store.append_message", {
621
+ chatId,
622
+ entryId: entry._id,
623
+ kind: entry.kind,
624
+ payloadBytes: payload.length,
625
+ queueDelayMs,
626
+ appendMs: Number((afterAppendAt - beforeAppendAt).toFixed(1)),
627
+ totalMs: Number((afterAppendAt - queuedAt).toFixed(1)),
628
+ })
599
629
  })
600
630
  return this.writeChain
601
631
  }
@@ -56,7 +56,9 @@ interface CreateWsRouterArgs {
56
56
  }
57
57
 
58
58
  function send(ws: ServerWebSocket<ClientState>, message: ServerEnvelope) {
59
- ws.send(JSON.stringify(message))
59
+ const payload = JSON.stringify(message)
60
+ ws.send(payload)
61
+ return payload.length
60
62
  }
61
63
 
62
64
  function ensureSnapshotSignatures(ws: ServerWebSocket<ClientState>) {
@@ -240,9 +242,12 @@ export function createWsRouter({
240
242
  }
241
243
  const snapshotSignatures = ensureSnapshotSignatures(ws)
242
244
  for (const [id, topic] of ws.data.subscriptions.entries()) {
245
+ const envelopeStartedAt = performance.now()
243
246
  const envelope = createEnvelope(id, topic)
247
+ const createdAt = performance.now()
244
248
  if (envelope.type !== "snapshot") continue
245
249
  const signature = JSON.stringify(envelope.snapshot)
250
+ const signatureReadyAt = performance.now()
246
251
  if (snapshotSignatures.get(id) === signature) {
247
252
  continue
248
253
  }
@@ -253,9 +258,19 @@ export function createWsRouter({
253
258
  chatId: topic.chatId,
254
259
  status: envelope.snapshot.data.runtime.status,
255
260
  messageCount: envelope.snapshot.data.messages.length,
261
+ buildMs: Number((createdAt - envelopeStartedAt).toFixed(1)),
262
+ signatureMs: Number((signatureReadyAt - createdAt).toFixed(1)),
263
+ signatureBytes: signature.length,
264
+ })
265
+ }
266
+ const payloadBytes = send(ws, envelope)
267
+ if (topic.type === "chat" && envelope.snapshot.type === "chat" && envelope.snapshot.data?.runtime.status === "starting") {
268
+ const profile = agent.getActiveTurnProfile(topic.chatId)
269
+ logSendToStartingProfile(profile?.traceId, profile?.startedAt, "ws.snapshot_send_completed", {
270
+ chatId: topic.chatId,
271
+ payloadBytes,
256
272
  })
257
273
  }
258
- send(ws, envelope)
259
274
  }
260
275
  }
261
276
 
@@ -473,7 +488,11 @@ export function createWsRouter({
473
488
  logSendToStartingProfile(profile?.traceId ?? command.clientTraceId, profile?.startedAt, "ws.chat_send_ack", {
474
489
  chatId: result.chatId ?? null,
475
490
  })
476
- send(ws, { v: PROTOCOL_VERSION, type: "ack", id, result })
491
+ const payloadBytes = send(ws, { v: PROTOCOL_VERSION, type: "ack", id, result })
492
+ logSendToStartingProfile(profile?.traceId ?? command.clientTraceId, profile?.startedAt, "ws.chat_send_ack_completed", {
493
+ chatId: result.chatId ?? null,
494
+ payloadBytes,
495
+ })
477
496
  break
478
497
  }
479
498
  case "chat.refreshDiffs": {