scream-code 0.13.3 → 0.13.4

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.
@@ -6,7 +6,7 @@ const __dirname = __cjsShimDirname(__filename);
6
6
  import { i as __require, o as __toESM, r as __exportAll, t as __commonJSMin } from "./chunk-D90kvbyJ.mjs";
7
7
  import { C as join$1, D as resolve$1, E as relative$1, S as isAbsolute$1, T as parse$7, a as isSupportedFile, b as basename$1, i as ingestFile, r as ingestDirectory, t as multiSearch, w as normalize, x as dirname$2, y as KnowledgeStore } from "./src-BH9W5k24.mjs";
8
8
  import { t as require_base64_js } from "./base64-js-DzVmk6Nb.mjs";
9
- import { a as setLocale, i as getLocale, n as assertScreamHostIdentity, o as t, r as createScreamDefaultHeaders, t as TextInputDialogComponent } from "./text-input-dialog-Cwnq9vFO.mjs";
9
+ import { a as setLocale, i as getLocale, n as assertScreamHostIdentity, o as t, r as createScreamDefaultHeaders, t as TextInputDialogComponent } from "./text-input-dialog-ClcJf9pu.mjs";
10
10
  import { createRequire } from "node:module";
11
11
  import { createHash, randomBytes, randomInt, randomUUID } from "node:crypto";
12
12
  import * as fs$1 from "node:fs/promises";
@@ -44525,22 +44525,25 @@ function extractUsage(usage) {
44525
44525
  const completionTokens = typeof u["completion_tokens"] === "number" ? u["completion_tokens"] : 0;
44526
44526
  let cached = 0;
44527
44527
  let other = 0;
44528
+ let created = 0;
44529
+ const details = typeof u["prompt_tokens_details"] === "object" && u["prompt_tokens_details"] !== null ? u["prompt_tokens_details"] : void 0;
44528
44530
  if (typeof u["prompt_cache_hit_tokens"] === "number") {
44529
44531
  cached = u["prompt_cache_hit_tokens"];
44530
44532
  other = typeof u["prompt_cache_miss_tokens"] === "number" ? u["prompt_cache_miss_tokens"] : Math.max(0, promptTokens - cached);
44531
44533
  } else {
44532
44534
  if (typeof u["cached_tokens"] === "number") cached = u["cached_tokens"];
44533
- else if (typeof u["prompt_tokens_details"] === "object" && u["prompt_tokens_details"] !== null) {
44534
- const details = u["prompt_tokens_details"];
44535
- if (typeof details["cached_tokens"] === "number") cached = details["cached_tokens"];
44536
- }
44535
+ else if (details !== void 0 && typeof details["cached_tokens"] === "number") cached = details["cached_tokens"];
44537
44536
  other = Math.max(0, promptTokens - cached);
44537
+ if (details !== void 0 && typeof details["cache_write_tokens"] === "number") {
44538
+ created = details["cache_write_tokens"];
44539
+ other = Math.max(0, other - created);
44540
+ }
44538
44541
  }
44539
44542
  return {
44540
44543
  inputOther: other,
44541
44544
  output: completionTokens,
44542
44545
  inputCacheRead: cached,
44543
- inputCacheCreation: 0
44546
+ inputCacheCreation: created
44544
44547
  };
44545
44548
  }
44546
44549
  /**
@@ -82866,7 +82869,7 @@ function restoreAgentRecord(agent, input) {
82866
82869
  agent.permission.recordApprovalResult(input);
82867
82870
  return;
82868
82871
  case "usage.record":
82869
- agent.usage.record(input.model, input.usage, "session");
82872
+ agent.usage.record(input.model, input.usage, input.usageScope ?? "session", { skipCurrentTurn: true });
82870
82873
  return;
82871
82874
  case "full_compaction.begin":
82872
82875
  agent.fullCompaction.begin(input);
@@ -96982,6 +96985,8 @@ const TURN_DEFAULTS = {
96982
96985
  };
96983
96986
  //#endregion
96984
96987
  //#region ../../packages/agent-core/src/agent/turn/index.ts
96988
+ /** Cap on how long the first turn waits for MCP servers to finish loading. */
96989
+ const MCP_WAIT_TIMEOUT_MS = 1e4;
96985
96990
  var TurnFlow = class {
96986
96991
  agent;
96987
96992
  steerBuffer = [];
@@ -97347,7 +97352,7 @@ var TurnFlow = class {
97347
97352
  async runTurn(turnId, signal) {
97348
97353
  let stopHookContinuationUsed = false;
97349
97354
  const deduper = new ToolCallDeduplicator();
97350
- await this.agent.mcp?.waitForInitialLoad(signal);
97355
+ await Promise.race([this.agent.mcp?.waitForInitialLoad(signal) ?? Promise.resolve(), new Promise((resolve) => setTimeout(resolve, MCP_WAIT_TIMEOUT_MS))]);
97351
97356
  while (true) {
97352
97357
  signal.throwIfAborted();
97353
97358
  const model = this.agent.config.model;
@@ -97933,6 +97938,14 @@ var UsageRecorder = class {
97933
97938
  agent;
97934
97939
  byModel = {};
97935
97940
  currentTurn;
97941
+ /**
97942
+ * Session-wide, turn-scoped usage only (`scope === 'turn'`). Restored from
97943
+ * the wire log on resume (records restore replays `usage.record` with its
97944
+ * original scope), so the TUI's per-session HitR survives process restarts
97945
+ * instead of resetting to zero. Compaction summaries (scope 'session')
97946
+ * never enter this total, matching the live turn.step.completed accumulation.
97947
+ */
97948
+ turnTotal;
97936
97949
  constructor(agent) {
97937
97950
  this.agent = agent;
97938
97951
  }
@@ -97942,7 +97955,7 @@ var UsageRecorder = class {
97942
97955
  endTurn() {
97943
97956
  this.currentTurn = void 0;
97944
97957
  }
97945
- record(model, usage, scope = "session") {
97958
+ record(model, usage, scope = "session", opts) {
97946
97959
  this.agent?.records.logRecord({
97947
97960
  type: "usage.record",
97948
97961
  model,
@@ -97951,7 +97964,10 @@ var UsageRecorder = class {
97951
97964
  });
97952
97965
  const current = this.byModel[model];
97953
97966
  this.byModel[model] = current === void 0 ? copyUsage(usage) : addUsage(current, usage);
97954
- if (scope === "turn") this.currentTurn = this.currentTurn === void 0 ? copyUsage(usage) : addUsage(this.currentTurn, usage);
97967
+ if (scope === "turn") {
97968
+ if (opts?.skipCurrentTurn !== true) this.currentTurn = this.currentTurn === void 0 ? copyUsage(usage) : addUsage(this.currentTurn, usage);
97969
+ this.turnTotal = this.turnTotal === void 0 ? copyUsage(usage) : addUsage(this.turnTotal, usage);
97970
+ }
97955
97971
  this.agent?.emitStatusUpdated();
97956
97972
  }
97957
97973
  data() {
@@ -97961,12 +97977,13 @@ var UsageRecorder = class {
97961
97977
  return {
97962
97978
  byModel: hasByModel ? byModel : void 0,
97963
97979
  total: hasByModel ? totalUsage(byModel) : void 0,
97964
- currentTurn: currentTurn === void 0 ? void 0 : copyUsage(currentTurn)
97980
+ currentTurn: currentTurn === void 0 ? void 0 : copyUsage(currentTurn),
97981
+ ...this.turnTotal !== void 0 ? { turnTotal: copyUsage(this.turnTotal) } : {}
97965
97982
  };
97966
97983
  }
97967
97984
  status() {
97968
97985
  const status = this.data();
97969
- if (status.byModel === void 0 && status.total === void 0 && status.currentTurn === void 0) return;
97986
+ if (status.byModel === void 0 && status.total === void 0 && status.currentTurn === void 0 && status.turnTotal === void 0) return;
97970
97987
  return status;
97971
97988
  }
97972
97989
  byModelSnapshot() {
@@ -102165,6 +102182,19 @@ var StdioMcpClient = class {
102165
102182
  await this.closeStartedClient();
102166
102183
  }
102167
102184
  /**
102185
+ * Synchronously terminate the child process, for the process-exit fallback
102186
+ * where `close()` (async, awaits transport cleanup) cannot run. The SDK
102187
+ * transport exposes the child pid but not the child handle, so we signal it
102188
+ * directly. Safe to call on an already-exited or never-started process.
102189
+ */
102190
+ killSync() {
102191
+ const pid = this.transport.pid;
102192
+ if (pid === null || pid <= 0) return;
102193
+ try {
102194
+ process.kill(pid, "SIGTERM");
102195
+ } catch {}
102196
+ }
102197
+ /**
102168
102198
  * Register a listener that fires when the underlying transport closes on
102169
102199
  * its own — i.e. the caller has not yet invoked {@link close}. At most one
102170
102200
  * listener can be installed; later registrations replace earlier ones.
@@ -102325,6 +102355,7 @@ var McpConnectionManager = class {
102325
102355
  this.options = options;
102326
102356
  this.oauthService = options.oauthService;
102327
102357
  this.log = options.log ?? log;
102358
+ process.on("exit", () => this.killAllSync());
102328
102359
  }
102329
102360
  /**
102330
102361
  * Returns the URL of an HTTP MCP server by name, or `undefined` for
@@ -102563,6 +102594,19 @@ var McpConnectionManager = class {
102563
102594
  await client.close();
102564
102595
  } catch {}
102565
102596
  }
102597
+ /**
102598
+ * Synchronously signal every still-running stdio child process. Registered
102599
+ * as a `process.on('exit')` fallback so MCP children never survive the host
102600
+ * — whether the app exits cleanly, is killed, or the terminal is closed.
102601
+ * `close()` (async) remains the graceful path; this only runs when the
102602
+ * event loop is already unwinding.
102603
+ */
102604
+ killAllSync() {
102605
+ for (const entry of this.entries.values()) {
102606
+ const client = entry.client;
102607
+ if (client instanceof StdioMcpClient) client.killSync();
102608
+ }
102609
+ }
102566
102610
  isCurrent(entry, attemptId) {
102567
102611
  return this.entries.get(entry.name) === entry && entry.attemptId === attemptId;
102568
102612
  }
@@ -121024,7 +121068,7 @@ var SDKRpcClient = class {
121024
121068
  const maxContextTokens = config.modelCapabilities?.max_context_tokens ?? 0;
121025
121069
  const contextTokens = context.tokenCount;
121026
121070
  const contextUsage = maxContextTokens > 0 ? contextTokens / maxContextTokens : 0;
121027
- const hasUsage = usage.byModel !== void 0 || usage.total !== void 0 || usage.currentTurn !== void 0;
121071
+ const hasUsage = usage.byModel !== void 0 || usage.total !== void 0 || usage.currentTurn !== void 0 || usage.turnTotal !== void 0;
121028
121072
  return {
121029
121073
  model: config.modelAlias ?? config.provider?.model,
121030
121074
  thinkingLevel: config.thinkingLevel,
@@ -122752,6 +122796,20 @@ const BUILTIN_SLASH_COMMANDS = [
122752
122796
  description: "registry.logout_desc",
122753
122797
  priority: 179
122754
122798
  },
122799
+ {
122800
+ name: "search",
122801
+ aliases: [],
122802
+ description: "registry.search_desc",
122803
+ priority: 178,
122804
+ availability: "always"
122805
+ },
122806
+ {
122807
+ name: "trace",
122808
+ aliases: [],
122809
+ description: "registry.trace_desc",
122810
+ priority: 177,
122811
+ availability: "always"
122812
+ },
122755
122813
  {
122756
122814
  name: "exit",
122757
122815
  aliases: ["quit", "q"],
@@ -122924,6 +122982,14 @@ const SESSION_TIPS = [
122924
122982
  {
122925
122983
  i18nKey: "editor.tip_12",
122926
122984
  isAd: false
122985
+ },
122986
+ {
122987
+ i18nKey: "editor.tip_13",
122988
+ isAd: false
122989
+ },
122990
+ {
122991
+ i18nKey: "editor.tip_14",
122992
+ isAd: false
122927
122993
  }
122928
122994
  ];
122929
122995
  /** Interval for random tip rotation (ms). */
@@ -124040,6 +124106,989 @@ async function handleDiyConfig(host) {
124040
124106
  host.showStatus(t("auth.connected", { name: `${providerId} · ${modelId} (${wire})` }));
124041
124107
  }
124042
124108
  //#endregion
124109
+ //#region src/tui/commands/search.ts
124110
+ /**
124111
+ * Open the full-screen conversation search overlay (same as Ctrl+Shift+F).
124112
+ * The overlay is owned by pi-tui; `openSearch` is a TS-private method but a
124113
+ * plain instance method at runtime, so we reach it through a cast instead of
124114
+ * adding an upstream API for a single caller.
124115
+ */
124116
+ function handleSearchCommand(host) {
124117
+ host.state.ui?.openSearch?.();
124118
+ }
124119
+ //#endregion
124120
+ //#region src/utils/trace/trace-builder.ts
124121
+ /**
124122
+ * Build trace cells from a session's wire log (`wire.jsonl`).
124123
+ *
124124
+ * The wire log records the full conversation trajectory: user prompts, model
124125
+ * requests (request.header), step content blocks (thinking / text / tool-call),
124126
+ * tool calls and results, usage records and compactions. This module replays
124127
+ * the log in order and flattens it into the closed `TraceCell` model.
124128
+ *
124129
+ * Parsing is intentionally loose (records are plain JSON) so the command does
124130
+ * not depend on the agent-core wire types; unknown/foreign records are
124131
+ * skipped defensively.
124132
+ */
124133
+ function asRecord(value) {
124134
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
124135
+ }
124136
+ function asString(value) {
124137
+ return typeof value === "string" ? value : void 0;
124138
+ }
124139
+ function asNumber(value) {
124140
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
124141
+ }
124142
+ function asRecordArray(value) {
124143
+ if (!Array.isArray(value)) return [];
124144
+ return value.flatMap((item) => {
124145
+ const rec = asRecord(item);
124146
+ return rec ? [rec] : [];
124147
+ });
124148
+ }
124149
+ function asStringArray(value) {
124150
+ if (!Array.isArray(value)) return [];
124151
+ return value.flatMap((item) => typeof item === "string" ? [item] : []);
124152
+ }
124153
+ /** Concatenate the text of content parts (text + thinking) for a prompt. */
124154
+ function contentPartsText(parts) {
124155
+ return asRecordArray(parts).map((part) => asString(part["text"]) ?? "").join("");
124156
+ }
124157
+ /**
124158
+ * Replay `wire.jsonl` and produce ordered trace cells.
124159
+ * Throws when the file is missing or contains no usable records.
124160
+ */
124161
+ function buildTraceCells({ wirePath }) {
124162
+ const rows = readWireRows(wirePath);
124163
+ if (rows.length === 0) throw new Error(`no wire records in ${wirePath}`);
124164
+ const cells = [];
124165
+ let lastTime;
124166
+ let nextIndex = 1;
124167
+ let lastCell;
124168
+ const pushCell = (kind, text, fields, time) => {
124169
+ if (lastCell && time !== void 0 && lastCell.endAt === void 0) lastCell.endAt = time;
124170
+ const seconds = time !== void 0 && lastTime !== void 0 ? (time - lastTime) / 1e3 : null;
124171
+ if (time !== void 0) lastTime = time;
124172
+ const cell = {
124173
+ index: nextIndex++,
124174
+ kind,
124175
+ text,
124176
+ timeSeconds: seconds,
124177
+ turn: turnNo,
124178
+ startedAt: time,
124179
+ ...fields
124180
+ };
124181
+ cells.push(cell);
124182
+ lastCell = cell;
124183
+ return cell;
124184
+ };
124185
+ let currentStepUuid;
124186
+ let currentStepStartTime;
124187
+ let currentBlocks = [];
124188
+ let currentBlock;
124189
+ let pendingTools = /* @__PURE__ */ new Map();
124190
+ let stepTools = [];
124191
+ let toolsInStep = [];
124192
+ let stepUsage;
124193
+ let stepFinishReason;
124194
+ let stepTtftMs;
124195
+ let stepDecodingMs;
124196
+ let stepModel;
124197
+ let currentTurnStart;
124198
+ let pendingSystem = [];
124199
+ let lastSystemTime;
124200
+ let turnNo = 0;
124201
+ const flushPendingSystem = (time) => {
124202
+ if (pendingSystem.length === 0) return;
124203
+ pushCell("system", pendingSystem.join(" · "), {
124204
+ requestOnly: true,
124205
+ sourceSeq: void 0,
124206
+ startedAt: lastSystemTime
124207
+ }, time);
124208
+ pendingSystem = [];
124209
+ lastSystemTime = void 0;
124210
+ };
124211
+ const finalizeStep = (time) => {
124212
+ if (currentStepUuid === void 0) return;
124213
+ const thinking = currentBlocks.filter((b) => b.type === "thinking").map((b) => b.text).join("");
124214
+ const text = currentBlocks.filter((b) => b.type === "text").map((b) => b.text).join("");
124215
+ const summary = text.trim().replaceAll(/\s+/g, " ").slice(0, 80) || (thinking.trim() ? "思考…" : "");
124216
+ const toolsText = toolsInStep.join(", ");
124217
+ const messageCell = pushCell("message", (toolsText ? `${summary}${summary ? " — " : ""}工具: ${toolsText}` : summary) || "(空回复)", {
124218
+ sourceSeq: void 0,
124219
+ inputDetail: void 0,
124220
+ outputDetail: text || void 0,
124221
+ thinkingDetail: thinking || void 0,
124222
+ input: stepUsage?.["inputOther"],
124223
+ cacheRead: stepUsage?.["inputCacheRead"],
124224
+ cacheWrite: stepUsage?.["inputCacheCreation"],
124225
+ output: stepUsage?.["output"],
124226
+ ttftMs: stepTtftMs,
124227
+ decodingMs: stepDecodingMs,
124228
+ model: stepModel,
124229
+ finishReason: stepFinishReason,
124230
+ startedAt: currentStepStartTime
124231
+ }, time);
124232
+ if (currentStepStartTime !== void 0 && time !== void 0) {
124233
+ messageCell.timeSeconds = (time - currentStepStartTime) / 1e3;
124234
+ messageCell.endAt = time;
124235
+ }
124236
+ for (const tool of stepTools) pushCell("tool", `${tool.name}${tool.isError ? " ✗" : " ✓"}`, {
124237
+ inputDetail: tool.argsText,
124238
+ outputDetail: tool.resultText || void 0,
124239
+ result: tool.resultText.replaceAll(/\s+/g, " ").slice(0, 80) || void 0,
124240
+ isError: tool.isError,
124241
+ sourceSeq: tool.callSeq,
124242
+ startedAt: tool.startedAt
124243
+ }, time);
124244
+ currentStepUuid = void 0;
124245
+ currentStepStartTime = void 0;
124246
+ currentBlocks = [];
124247
+ currentBlock = void 0;
124248
+ pendingTools = /* @__PURE__ */ new Map();
124249
+ stepTools = [];
124250
+ toolsInStep = [];
124251
+ stepUsage = void 0;
124252
+ stepFinishReason = void 0;
124253
+ stepTtftMs = void 0;
124254
+ stepDecodingMs = void 0;
124255
+ stepModel = void 0;
124256
+ };
124257
+ const handleLoopEvent = (event, time, seq) => {
124258
+ switch (asString(event["type"])) {
124259
+ case "step.begin":
124260
+ currentStepUuid = asString(event["stepUuid"]) ?? asString(event["uuid"]);
124261
+ currentStepStartTime = time;
124262
+ currentBlocks = [];
124263
+ currentBlock = void 0;
124264
+ pendingTools = /* @__PURE__ */ new Map();
124265
+ toolsInStep = [];
124266
+ break;
124267
+ case "block.start": {
124268
+ const blockType = asString(event["blockType"]);
124269
+ if (blockType === "thinking" || blockType === "text") {
124270
+ currentBlock = {
124271
+ type: blockType,
124272
+ text: ""
124273
+ };
124274
+ currentBlocks.push(currentBlock);
124275
+ }
124276
+ break;
124277
+ }
124278
+ case "content.part": {
124279
+ const part = asRecord(event["part"]);
124280
+ const text = asString(part?.["text"]) ?? asString(part?.["think"]) ?? "";
124281
+ if (!text) break;
124282
+ const isThink = part?.["type"] === "think" || part?.["type"] === "thinking";
124283
+ if (currentBlock) currentBlock.text += text;
124284
+ else {
124285
+ const fallback = currentBlocks.at(-1);
124286
+ if (fallback && fallback.type === (isThink ? "thinking" : "text")) fallback.text += text;
124287
+ else currentBlocks.push({
124288
+ type: isThink ? "thinking" : "text",
124289
+ text
124290
+ });
124291
+ }
124292
+ break;
124293
+ }
124294
+ case "block.end":
124295
+ currentBlock = void 0;
124296
+ break;
124297
+ case "tool.call": {
124298
+ const name = asString(event["name"]) ?? "tool";
124299
+ const args = event["args"];
124300
+ const argsText = typeof args === "string" ? args : JSON.stringify(args ?? "");
124301
+ const toolCallId = asString(event["toolCallId"]) ?? asString(event["uuid"]) ?? `${name}-${seq}`;
124302
+ pendingTools.set(toolCallId, {
124303
+ name,
124304
+ argsText,
124305
+ resultText: "",
124306
+ startedAt: time,
124307
+ callSeq: seq
124308
+ });
124309
+ if (!toolsInStep.includes(name)) toolsInStep.push(name);
124310
+ break;
124311
+ }
124312
+ case "tool.result": {
124313
+ const toolCallId = asString(event["toolCallId"]) ?? "";
124314
+ const pending = pendingTools.get(toolCallId);
124315
+ const resultRec = asRecord(event["result"]);
124316
+ const isError = resultRec?.["isError"] === true || resultRec?.["is_error"] === true || asString(resultRec?.["error_name"]) !== void 0;
124317
+ const resultText = asString(resultRec?.["output"]) ?? asString(resultRec?.["result"]) ?? asString(resultRec?.["error_message"]) ?? "";
124318
+ if (pending) {
124319
+ pending.resultText = resultText;
124320
+ pending.isError = isError;
124321
+ stepTools.push(pending);
124322
+ pendingTools.delete(toolCallId);
124323
+ }
124324
+ break;
124325
+ }
124326
+ case "step.end": {
124327
+ const usage = asRecord(event["usage"]);
124328
+ if (usage) stepUsage = {
124329
+ inputOther: asNumber(usage["inputOther"]) ?? 0,
124330
+ inputCacheRead: asNumber(usage["inputCacheRead"]) ?? 0,
124331
+ inputCacheCreation: asNumber(usage["inputCacheCreation"]) ?? 0,
124332
+ output: asNumber(usage["output"]) ?? 0
124333
+ };
124334
+ stepFinishReason = asString(event["finishReason"]);
124335
+ stepTtftMs = asNumber(event["llmFirstTokenLatencyMs"]);
124336
+ stepDecodingMs = asNumber(event["llmStreamDurationMs"]);
124337
+ stepModel = asString(event["reportedModel"]);
124338
+ finalizeStep(time);
124339
+ break;
124340
+ }
124341
+ default: break;
124342
+ }
124343
+ };
124344
+ for (const { seq, time, record } of rows) switch (asString(record["type"])) {
124345
+ case "context.append_loop_event": {
124346
+ const event = asRecord(record["event"]);
124347
+ if (!event) break;
124348
+ handleLoopEvent(event, time, seq);
124349
+ break;
124350
+ }
124351
+ case "turn.prompt": {
124352
+ finalizeStep(time);
124353
+ turnNo += 1;
124354
+ flushPendingSystem(time);
124355
+ const input = record["input"];
124356
+ const text = contentPartsText(input).trim();
124357
+ pushCell("user", text.replaceAll(/\s+/g, " ").slice(0, 80) || "(空输入)", {
124358
+ opensTurn: true,
124359
+ inputDetail: text || void 0,
124360
+ sourceSeq: seq
124361
+ }, time);
124362
+ currentTurnStart = time;
124363
+ break;
124364
+ }
124365
+ case "turn.steer": {
124366
+ const input = record["input"];
124367
+ const text = contentPartsText(input).trim();
124368
+ pushCell("context", `转向: ${text.replaceAll(/\s+/g, " ").slice(0, 80)}`, {
124369
+ inputDetail: text || void 0,
124370
+ sourceSeq: seq
124371
+ }, time);
124372
+ break;
124373
+ }
124374
+ case "request.header": {
124375
+ const provider = asString(record["provider"]) ?? "";
124376
+ const model = asString(record["model"]) ?? "";
124377
+ const tools = asRecordArray(record["activeTools"]).map((t) => asString(t["name"]) ?? "");
124378
+ pushCell("system", `请求 ${provider ? `${provider}/` : ""}${model}`, {
124379
+ requestOnly: true,
124380
+ inputDetail: tools.length > 0 ? `工具: ${tools.join(", ")}` : void 0,
124381
+ sourceSeq: seq
124382
+ }, time);
124383
+ break;
124384
+ }
124385
+ case "tools.set_active_tools": {
124386
+ const names = asStringArray(record["names"]).length > 0 ? asStringArray(record["names"]) : asRecordArray(record["names"]).map((n) => asString(n["name"]) ?? "");
124387
+ pendingSystem.push(`工具集: ${names.join(", ")}`);
124388
+ lastSystemTime = time;
124389
+ break;
124390
+ }
124391
+ case "config.update": {
124392
+ const cfg = asRecord(record);
124393
+ const bits = [];
124394
+ if (asString(cfg?.["modelAlias"])) bits.push(`模型别名: ${cfg["modelAlias"]}`);
124395
+ if (asString(cfg?.["systemPrompt"])) bits.push("系统提示词已更新");
124396
+ if (bits.length === 0) break;
124397
+ pendingSystem.push(bits.join(" · "));
124398
+ lastSystemTime = time;
124399
+ break;
124400
+ }
124401
+ case "usage.record":
124402
+ if (currentStepUuid === void 0) {
124403
+ const usage = asRecord(record["usage"]);
124404
+ pushCell("context", "usage", {
124405
+ input: asNumber(usage?.["inputOther"]),
124406
+ cacheRead: asNumber(usage?.["inputCacheRead"]),
124407
+ cacheWrite: asNumber(usage?.["inputCacheCreation"]),
124408
+ output: asNumber(usage?.["output"]),
124409
+ sourceSeq: seq
124410
+ }, time);
124411
+ }
124412
+ break;
124413
+ case "full_compaction.begin": {
124414
+ finalizeStep(time);
124415
+ const reason = asString(record["reason"]);
124416
+ const instruction = asString(record["instruction"]);
124417
+ const source = asString(record["source"]);
124418
+ pushCell("compacted", `压缩上下文${reason ? `(${reason})` : ""}`, {
124419
+ sourceSeq: seq,
124420
+ startedAt: currentTurnStart,
124421
+ inputDetail: instruction || void 0,
124422
+ result: source ? `来源: ${source}` : void 0
124423
+ }, time);
124424
+ break;
124425
+ }
124426
+ case "micro_compaction.apply": {
124427
+ finalizeStep(time);
124428
+ const reason = asString(record["reason"]);
124429
+ pushCell("compacted", `微压缩${reason ? `(${reason})` : ""}`, {
124430
+ sourceSeq: seq,
124431
+ startedAt: currentTurnStart
124432
+ }, time);
124433
+ break;
124434
+ }
124435
+ default: break;
124436
+ }
124437
+ finalizeStep(void 0);
124438
+ flushPendingSystem(void 0);
124439
+ return cells;
124440
+ }
124441
+ function readWireRows(wirePath) {
124442
+ const content = readFileSync(wirePath, "utf8");
124443
+ const rows = [];
124444
+ let seq = 0;
124445
+ for (const line of content.split("\n")) {
124446
+ if (!line.trim()) continue;
124447
+ seq += 1;
124448
+ try {
124449
+ const rec = asRecord(JSON.parse(line));
124450
+ if (!rec) continue;
124451
+ const time = asNumber(rec["time"]);
124452
+ rows.push({
124453
+ seq,
124454
+ time,
124455
+ record: rec
124456
+ });
124457
+ } catch {}
124458
+ }
124459
+ return rows;
124460
+ }
124461
+ //#endregion
124462
+ //#region src/utils/trace/render-trace-html.ts
124463
+ const KIND_LABELS = {
124464
+ system: "SYSTEM",
124465
+ user: "USER",
124466
+ context: "CONTEXT",
124467
+ compacted: "COMPACTED",
124468
+ message: "ASSISTANT",
124469
+ tool: "TOOL"
124470
+ };
124471
+ const KIND_TAG_STYLE = {
124472
+ system: "color:#CFD3D6;background:#353638",
124473
+ user: "color:#679EFE;background:#34415B",
124474
+ context: "color:#59C984;background:#233C2C",
124475
+ compacted: "color:#CFD3D6;background:#353638",
124476
+ message: "color:#9474BC;background:#352F3A",
124477
+ tool: "color:#DD8629;background:#27241F"
124478
+ };
124479
+ const SPAN_COLORS = {
124480
+ system: "#353638",
124481
+ user: "#679EFE",
124482
+ context: "#59C984",
124483
+ compacted: "#CFD3D6",
124484
+ message: "#8C6BB5",
124485
+ tool: "#DD8629"
124486
+ };
124487
+ const KIND_LANE = {
124488
+ user: 0,
124489
+ context: 1,
124490
+ message: 1,
124491
+ compacted: 1,
124492
+ tool: 2,
124493
+ system: 1
124494
+ };
124495
+ const CSS = `
124496
+ :root { color-scheme: dark; }
124497
+ * { box-sizing: border-box; }
124498
+ html, body { height: 100%; margin: 0; }
124499
+ body {
124500
+ background: #232324; color: #F9FAFB;
124501
+ font: 13px/20px -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
124502
+ "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
124503
+ }
124504
+ .mono { font-family: "SF Mono", "JetBrains Mono", "Fira Code", Consolas, Menlo, monospace; }
124505
+ #root { display: flex; flex-direction: column; height: 100%; }
124506
+ .toolbar {
124507
+ flex: 0 0 32px; display: flex; align-items: center; gap: 10px;
124508
+ padding: 0 6px; border-bottom: 1px solid rgba(255,255,255,.12);
124509
+ background: #232324;
124510
+ }
124511
+ .toolbar .title { font-size: 13px; font-weight: 500; color: #CFD3D6; padding-left: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
124512
+ .toolbar .count { font-size: 11px; color: #81858C; white-space: nowrap; }
124513
+ .toolbar .btn {
124514
+ height: 22px; padding: 0 10px; border: 1px solid rgba(255,255,255,.12);
124515
+ border-radius: 4px; background: #2C2C2E; color: #CFD3D6; font-size: 12px; cursor: pointer;
124516
+ white-space: nowrap;
124517
+ }
124518
+ .toolbar .btn:hover { background: #353638; }
124519
+ .toolbar .btn.on { border-color: #679EFE; color: #F9FAFB; background: #232324; }
124520
+ .toolbar .search {
124521
+ margin-left: auto; display: flex; align-items: center;
124522
+ flex: 0 1 220px; min-width: 84px; height: 22px; padding: 0 8px;
124523
+ border: 1px solid rgba(255,255,255,.12); border-radius: 4px; background: #2C2C2E;
124524
+ }
124525
+ .toolbar .search:focus-within { border-color: #679EFE; background: #232324; }
124526
+ .toolbar .search input { flex: 1; min-width: 0; border: 0; outline: 0; background: transparent; color: #F9FAFB; font-size: 12px; }
124527
+ .toolbar .search input::placeholder { color: #81858C; }
124528
+ .timeline {
124529
+ flex: 0 0 44px; position: relative; border-bottom: 1px solid rgba(255,255,255,.12);
124530
+ background: #1B1B1C; overflow: hidden; cursor: grab;
124531
+ }
124532
+ .timeline .lane-label { position: absolute; left: 4px; font-size: 10px; color: #81858C; line-height: 13px; }
124533
+ .timeline .track { position: absolute; left: 74px; right: 8px; top: 4px; bottom: 4px; }
124534
+ .locator {
124535
+ position: absolute; top: -4px; bottom: -4px; width: 2px; background: #679EFE;
124536
+ cursor: ew-resize; z-index: 6; pointer-events: auto; box-shadow: 0 0 6px rgba(103,158,254,.8);
124537
+ }
124538
+ .locator::after {
124539
+ content: ''; position: absolute; top: 0; left: -4px; width: 10px; height: 10px;
124540
+ background: #679EFE; border-radius: 2px;
124541
+ }
124542
+ .timeline .span {
124543
+ position: absolute; height: 9px; border-radius: 2px; min-width: 2px; cursor: pointer;
124544
+ border: 1px solid rgba(0,0,0,.25);
124545
+ }
124546
+ .timeline .span:hover { outline: 1px solid #F9FAFB; }
124547
+ .timeline .span.active { outline: 2px solid #679EFE; }
124548
+ .timeline .turnTick { position: absolute; top: 0; bottom: 0; width: 1px; background: rgba(255,255,255,.22); }
124549
+ .tip {
124550
+ position: fixed; z-index: 30; pointer-events: none; max-width: 340px;
124551
+ background: #2C2C2E; border: 1px solid rgba(255,255,255,.2); border-radius: 6px;
124552
+ padding: 8px 10px; font-size: 12px; line-height: 17px; box-shadow: 0 4px 14px rgba(0,0,0,.5);
124553
+ display: none; white-space: normal; word-break: break-word;
124554
+ }
124555
+ .tip .tip-title { font-weight: 600; color: #F9FAFB; }
124556
+ .tip .tip-facts { color: #ADB2B8; margin-top: 2px; }
124557
+ .tip .tip-body { color: #CFD3D6; margin-top: 2px; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
124558
+ .split { display: flex; flex: 1; min-height: 0; }
124559
+ .tablePane { flex: 1; overflow-y: auto; overflow-x: hidden; }
124560
+ table { width: 100%; border-spacing: 0; table-layout: fixed; }
124561
+ col.event-column { width: 122px; }
124562
+ td { height: 30px; padding: 0 8px; border-bottom: 1px solid rgba(255,255,255,.06); vertical-align: middle; }
124563
+ td.event { padding-left: 10px; white-space: nowrap; }
124564
+ td.content { padding-left: 4px; }
124565
+ tr.row { cursor: pointer; }
124566
+ tr.row { content-visibility: auto; contain-intrinsic-size: 30px; }
124567
+ tr.row:hover { background: rgba(255,255,255,.08); }
124568
+ tr.row.selected { background: rgba(255,255,255,.14); }
124569
+ tr.row.selected td { box-shadow: inset 1px 0 0 #679EFE; }
124570
+ tr.turnrow td { background: #1B1B1C; font-weight: 500; }
124571
+ .kindTag {
124572
+ display: inline-flex; align-items: center; height: 19px; padding: 0 5px;
124573
+ border-radius: 4px; font-size: 10px; font-weight: 650; line-height: 16px;
124574
+ letter-spacing: .035em; max-width: 96px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
124575
+ }
124576
+ .seq { margin-left: 6px; font-size: 11px; color: #81858C; }
124577
+ .summary { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; color: #F9FAFB; }
124578
+ .toolline { font-family: "SF Mono", "JetBrains Mono", Consolas, Menlo, monospace; font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
124579
+ .toolline .tname { color: #F9FAFB; }
124580
+ .toolline .targs { margin-left: 7px; color: #ADB2B8; }
124581
+ .toolline .tarrow { margin-left: 7px; color: #81858C; }
124582
+ .toolline .tresult { margin-left: 7px; color: #CFD3D6; }
124583
+ .toolline .terror { margin-left: 7px; color: #F25A5A; }
124584
+ .toolline .tempty { margin-left: 7px; color: #81858C; }
124585
+ .facts { color: #81858C; font-size: 11px; margin-left: 8px; display: inline; }
124586
+ .detail {
124587
+ width: clamp(320px, 38%, 440px); max-width: calc(100% - 280px);
124588
+ border-left: 1px solid rgba(255,255,255,.12); background: #232324;
124589
+ display: flex; flex-direction: column; min-height: 0;
124590
+ }
124591
+ .detail.hidden { display: none; }
124592
+ .detail .dhead {
124593
+ flex: 0 0 42px; display: flex; align-items: center; gap: 8px;
124594
+ padding: 0 8px 0 12px; border-bottom: 1px solid rgba(255,255,255,.12);
124595
+ }
124596
+ .detail .dhead .dname { font-size: 12px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
124597
+ .detail .dhead .dclose { margin-left: auto; width: 28px; height: 28px; border: 0; border-radius: 6px; background: transparent; color: #ADB2B8; font-size: 18px; cursor: pointer; }
124598
+ .detail .dhead .dclose:hover { background: rgba(255,255,255,.08); }
124599
+ .detail .dbody { flex: 1; overflow-y: auto; padding: 12px 14px; }
124600
+ .ovgrid { display: grid; grid-template-columns: 94px minmax(0, 1fr); gap: 2px 12px; font-size: 13px; }
124601
+ .ovgrid dt { color: #ADB2B8; }
124602
+ .ovgrid dd { margin: 0; color: #F9FAFB; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
124603
+ .section { margin-top: 16px; }
124604
+ .section h4 { margin: 0 0 4px; font-size: 11px; font-weight: 500; color: #CFD3D6; text-transform: uppercase; }
124605
+ .payload {
124606
+ font-family: "SF Mono", "JetBrains Mono", "Fira Code", Consolas, Menlo, monospace;
124607
+ font-size: 12px; line-height: 19px; background: #1B1B1C; padding: 14px;
124608
+ border-radius: 4px; white-space: pre-wrap; word-break: break-word; color: #CFD3D6;
124609
+ }
124610
+ .payload.error { color: #F25A5A; }
124611
+ .placeholder { color: #81858C; padding: 32px; text-align: center; }
124612
+ `;
124613
+ const RENDER_JS = `
124614
+ var cells = JSON.parse(document.getElementById('data').textContent);
124615
+ var labels = ${JSON.stringify(KIND_LABELS)};
124616
+ var tagStyles = ${JSON.stringify(KIND_TAG_STYLE)};
124617
+ var spanColors = ${JSON.stringify(SPAN_COLORS)};
124618
+ var laneOf = ${JSON.stringify(KIND_LANE)};
124619
+ var tbody = document.getElementById('rows');
124620
+ var drawer = document.getElementById('detail');
124621
+ var drawerName = document.getElementById('dname');
124622
+ var drawerBody = document.getElementById('dbody');
124623
+ var searchInput = document.getElementById('q');
124624
+ var timeline = document.getElementById('timeline-track');
124625
+ var track = timeline;
124626
+ var tablePane = document.querySelector('.tablePane');
124627
+ var locator = document.getElementById('locator');
124628
+ var currentFiltered = [];
124629
+ var turnsBtn = document.getElementById('turns');
124630
+ var callsBtn = document.getElementById('calls');
124631
+ var modeBtn = document.getElementById('mode');
124632
+ var jsonBtn = document.getElementById('json');
124633
+ var tip = document.getElementById('tip');
124634
+ var collapsedTurns = false;
124635
+ var collapsedCalls = false;
124636
+ var timeMode = false;
124637
+ var selectedIndex = -1;
124638
+ var rowEls = [];
124639
+ function showTip(text, x, y) {
124640
+ tip.innerHTML = text;
124641
+ tip.style.display = 'block';
124642
+ var w = tip.offsetWidth, h = tip.offsetHeight;
124643
+ var left = x + 14, top = y + 14;
124644
+ if (left + w > window.innerWidth - 8) left = x - w - 14;
124645
+ if (top + h > window.innerHeight - 8) top = y - h - 14;
124646
+ tip.style.left = Math.max(4, left) + 'px';
124647
+ tip.style.top = Math.max(4, top) + 'px';
124648
+ }
124649
+ function hideTip() { tip.style.display = 'none'; }
124650
+ function fmtMs(v) { if (v === undefined || v === null) return null; if (v < 1000) return v + ' ms'; return (v / 1000).toFixed(2) + ' s'; }
124651
+ function timingFacts(cell) {
124652
+ var parts = [];
124653
+ var ttft = fmtMs(cell.ttftMs), dec = fmtMs(cell.decodingMs);
124654
+ if (ttft) parts.push('TTFT ' + ttft);
124655
+ if (dec) parts.push('解码 ' + dec);
124656
+ if (cell.model) parts.push('模型 ' + cell.model);
124657
+ if (cell.finishReason) parts.push('结束 ' + cell.finishReason);
124658
+ return parts;
124659
+ }
124660
+ function esc(v) { return String(v).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); }
124661
+ function fmtSeconds(s) {
124662
+ if (s === null || s === undefined) return '—';
124663
+ if (s < 1) return Math.round(s * 1000) + ' ms';
124664
+ return s.toFixed(2) + ' s';
124665
+ }
124666
+ function toolContent(cell) {
124667
+ var html = '<span class="tname">' + esc(cell.text) + '</span>';
124668
+ if (cell.inputDetail) html += '<span class="targs">' + esc(cell.inputDetail) + '</span>';
124669
+ if (cell.isError) html += '<span class="terror">→ ' + esc(cell.result || 'failed') + '</span>';
124670
+ else if (cell.result) html += '<span class="tarrow">→</span><span class="tresult">' + esc(cell.result) + '</span>';
124671
+ else html += '<span class="tempty">→ No output</span>';
124672
+ return html;
124673
+ }
124674
+ function overviewRows(cell) {
124675
+ var rows = [['类型', labels[cell.kind] || cell.kind], ['序号', '#' + cell.index], ['耗时', fmtSeconds(cell.timeSeconds)]];
124676
+ if (cell.turn) rows.push(['回合', String(cell.turn)]);
124677
+ if (cell.input !== undefined) rows.push(['输入', String(cell.input)]);
124678
+ if (cell.cacheRead) rows.push(['缓存读', String(cell.cacheRead)]);
124679
+ if (cell.cacheWrite) rows.push(['缓存写', String(cell.cacheWrite)]);
124680
+ if (cell.output !== undefined) rows.push(['输出', String(cell.output)]);
124681
+ var ttft = fmtMs(cell.ttftMs);
124682
+ if (ttft) rows.push(['TTFT', ttft]);
124683
+ var dec = fmtMs(cell.decodingMs);
124684
+ if (dec) rows.push(['解码', dec]);
124685
+ if (cell.model) rows.push(['模型', cell.model]);
124686
+ if (cell.finishReason) rows.push(['结束', cell.finishReason]);
124687
+ return rows.map(function (r) { return '<dt>' + esc(r[0]) + '</dt><dd>' + esc(r[1]) + '</dd>'; }).join('');
124688
+ }
124689
+ function section(title, value, cls) {
124690
+ if (!value) return '';
124691
+ return '<div class="section"><h4>' + title + '</h4><div class="payload' + (cls ? ' ' + cls : '') + '">' + esc(value) + '</div></div>';
124692
+ }
124693
+ function showDetail(i) {
124694
+ if (selectedIndex === i) { hideDetail(); return; }
124695
+ selectedIndex = i;
124696
+ var cell = cells[i];
124697
+ for (var k = 0; k < rowEls.length; k++) rowEls[k].classList.remove('selected');
124698
+ if (rowEls[i]) {
124699
+ rowEls[i].classList.add('selected');
124700
+ if (rowEls[i].scrollIntoView) rowEls[i].scrollIntoView({ block: 'center' });
124701
+ }
124702
+ var spans = timeline.querySelectorAll('.span');
124703
+ for (var s = 0; s < spans.length; s++) spans[s].classList.remove('active');
124704
+ if (timeline.querySelector('span[data-i="' + i + '"]')) timeline.querySelector('span[data-i="' + i + '"]').classList.add('active');
124705
+ drawerName.textContent = (labels[cell.kind] || cell.kind) + ' #' + cell.index;
124706
+ var html = '<dl class="ovgrid">' + overviewRows(cell) + '</dl>';
124707
+ html += section('思考', cell.thinkingDetail);
124708
+ html += section('内容', cell.outputDetail);
124709
+ html += section('输入', cell.inputDetail);
124710
+ if (cell.kind === 'tool') html += section('工具结果', cell.result || cell.outputDetail, cell.isError ? 'error' : '');
124711
+ drawerBody.innerHTML = html || '<div class="placeholder">无详情</div>';
124712
+ drawer.classList.remove('hidden');
124713
+ }
124714
+ function hideDetail() {
124715
+ selectedIndex = -1;
124716
+ drawer.classList.add('hidden');
124717
+ for (var k = 0; k < rowEls.length; k++) rowEls[k].classList.remove('selected');
124718
+ var spans = timeline.querySelectorAll('.span');
124719
+ for (var s = 0; s < spans.length; s++) spans[s].classList.remove('active');
124720
+ }
124721
+ function renderTimeline(visible) {
124722
+ timeline.innerHTML = '';
124723
+ if (visible.length < 2) return;
124724
+ var n = visible.length;
124725
+ if (timeMode && visible.every(function (c) { return c.startedAt !== undefined; })) {
124726
+ var min = Infinity, max = -Infinity;
124727
+ for (var i = 0; i < n; i++) {
124728
+ var s = visible[i].startedAt, e = visible[i].endAt !== undefined ? visible[i].endAt : (s || 0) + 1000;
124729
+ if (s < min) min = s;
124730
+ if (e > max) max = e;
124731
+ }
124732
+ var total = max - min;
124733
+ var idleCap = total * 0.05; // compress idle gaps longer than 5% of the span
124734
+ var cursor = min;
124735
+ var scaled = [];
124736
+ for (var j = 0; j < n; j++) {
124737
+ var cs = visible[j].startedAt;
124738
+ var ce = visible[j].endAt !== undefined ? visible[j].endAt : cs + 1000;
124739
+ var gap = cs - cursor;
124740
+ if (gap > idleCap) { min += gap - idleCap; max -= gap - idleCap; }
124741
+ cursor = ce;
124742
+ scaled.push([cs - min, ce - min]);
124743
+ }
124744
+ total = max - min;
124745
+ for (var k = 0; k < n; k++) {
124746
+ var span = makeSpan(visible[k], k, (scaled[k][0] / total) * 100, (scaled[k][1] - scaled[k][0]) / total * 100);
124747
+ timeline.appendChild(span);
124748
+ }
124749
+ } else {
124750
+ var widthPct = 100 / n;
124751
+ for (var m = 0; m < n; m++) {
124752
+ var sp = makeSpan(visible[m], m, m * widthPct, widthPct - 0.4);
124753
+ timeline.appendChild(sp);
124754
+ }
124755
+ }
124756
+ // Turn boundary ticks (time mode uses the scaled coordinates).
124757
+ var prevTurn = null;
124758
+ for (var t = 0; t < n; t++) {
124759
+ var tn = visible[t].turn || 0;
124760
+ if (prevTurn !== null && tn !== prevTurn) {
124761
+ var tick = document.createElement('span');
124762
+ tick.className = 'turnTick';
124763
+ if (timeMode && scaled) {
124764
+ tick.style.left = (scaled[t][0] / total * 100) + '%';
124765
+ } else {
124766
+ tick.style.left = (t * 100 / n) + '%';
124767
+ }
124768
+ timeline.appendChild(tick);
124769
+ }
124770
+ prevTurn = tn;
124771
+ }
124772
+ }
124773
+ function makeSpan(cell, idx, leftPct, widthPct) {
124774
+ var span = document.createElement('span');
124775
+ span.className = 'span';
124776
+ span.style.left = Math.max(0, leftPct) + '%';
124777
+ span.style.width = 'max(2px, ' + Math.max(0.3, widthPct) + '%)';
124778
+ span.style.top = (laneOf[cell.kind] || 1) * 13 + 'px';
124779
+ span.style.background = spanColors[cell.kind] || '#353638';
124780
+ span.setAttribute('data-i', String(idx));
124781
+ span.title = '';
124782
+ span.addEventListener('mouseenter', function (e) {
124783
+ if (rowEls[idx]) rowEls[idx].classList.add('hover');
124784
+ if (cells.length <= 2000) {
124785
+ var facts = timingFacts(cell);
124786
+ var ftext = [];
124787
+ if (cell.timeSeconds !== null && cell.timeSeconds !== undefined) ftext.push('耗时 ' + cell.timeSeconds.toFixed(1) + 's');
124788
+ ftext = ftext.concat(facts);
124789
+ showTip('<div class="tip-title">#' + cell.index + ' ' + (labels[cell.kind] || cell.kind) + '</div>' +
124790
+ (ftext.length ? '<div class="tip-facts">' + ftext.join(' · ') + '</div>' : '') +
124791
+ '<div class="tip-body">' + esc(cell.text) + '</div>', e.clientX, e.clientY);
124792
+ }
124793
+ });
124794
+ span.addEventListener('mousemove', function (e) { if (cells.length <= 2000) { tip.style.left = '0px'; tip.style.top = '0px'; showTip(tip.innerHTML, e.clientX, e.clientY); } });
124795
+ span.addEventListener('mouseleave', function () { if (rowEls[idx]) rowEls[idx].classList.remove('hover'); hideTip(); });
124796
+ span.addEventListener('click', function (e) {
124797
+ e.stopPropagation();
124798
+ showDetail(idx);
124799
+ });
124800
+ return span;
124801
+ }
124802
+ function render() {
124803
+ var q = (searchInput.value || '').toLowerCase();
124804
+ // Keep every cell (including requestOnly system rows) so ledger indices
124805
+ // stay aligned with the cells array; the timeline renders them too.
124806
+ currentFiltered = cells.filter(function (c) {
124807
+ if (collapsedCalls && c.kind === 'tool') return false;
124808
+ if (q && !(c.text + ' ' + (c.outputDetail || '') + ' ' + (c.thinkingDetail || '')).toLowerCase().includes(q)) return false;
124809
+ return true;
124810
+ });
124811
+ var filtered = currentFiltered;
124812
+ renderTimeline(filtered);
124813
+ tbody.innerHTML = '';
124814
+ rowEls = [];
124815
+ var shown = 0;
124816
+ var lastTurn = null;
124817
+ var turnCounts = {};
124818
+ for (var i = 0; i < filtered.length; i++) turnCounts[filtered[i].turn || 0] = (turnCounts[filtered[i].turn || 0] || 0) + 1;
124819
+ for (var i2 = 0; i2 < filtered.length; i2++) {
124820
+ var cell = filtered[i2];
124821
+ var turn = cell.turn || 0;
124822
+ var row;
124823
+ if (collapsedTurns) {
124824
+ // Collapsed mode: one summary row per turn; cell rows are skipped.
124825
+ if (turn !== lastTurn) {
124826
+ var trow = document.createElement('tr');
124827
+ trow.className = 'row turnrow';
124828
+ var tev = document.createElement('td');
124829
+ tev.className = 'event';
124830
+ tev.innerHTML = '<span class="kindTag" style="' + tagStyles.user + '">TURN</span><span class="seq">' + turn + '</span>';
124831
+ var tco = document.createElement('td');
124832
+ tco.className = 'content';
124833
+ var tsum = document.createElement('div');
124834
+ tsum.className = 'summary';
124835
+ tsum.textContent = cell.text;
124836
+ tco.appendChild(tsum);
124837
+ var tfacts = document.createElement('span');
124838
+ tfacts.className = 'facts';
124839
+ tfacts.textContent = '· ' + (turnCounts[turn] || 0) + ' 条';
124840
+ tco.appendChild(tfacts);
124841
+ trow.appendChild(tev); trow.appendChild(tco);
124842
+ trow.addEventListener('click', (function (t) {
124843
+ return function () {
124844
+ collapsedTurns = false;
124845
+ if (turnsBtn) turnsBtn.classList.remove('on');
124846
+ render();
124847
+ var idx = currentFiltered.findIndex(function (c) { return c.turn === t; });
124848
+ if (idx >= 0 && rowEls[idx]) { rowEls[idx].scrollIntoView({ block: 'center' }); showDetail(idx); }
124849
+ };
124850
+ })(turn));
124851
+ tbody.appendChild(trow);
124852
+ shown++;
124853
+ lastTurn = turn;
124854
+ }
124855
+ continue;
124856
+ }
124857
+ row = document.createElement('tr');
124858
+ row.className = 'row';
124859
+ if (selectedIndex === i2) row.classList.add('selected');
124860
+ var tag = document.createElement('span');
124861
+ tag.className = 'kindTag';
124862
+ tag.setAttribute('style', tagStyles[cell.kind]);
124863
+ tag.textContent = labels[cell.kind] || cell.kind;
124864
+ var seq = document.createElement('span');
124865
+ seq.className = 'seq';
124866
+ seq.textContent = '#' + cell.index;
124867
+ var eventTd = document.createElement('td');
124868
+ eventTd.className = 'event';
124869
+ eventTd.appendChild(tag); eventTd.appendChild(seq);
124870
+ var contentTd = document.createElement('td');
124871
+ contentTd.className = 'content';
124872
+ if (cell.kind === 'tool') {
124873
+ var tl = document.createElement('div');
124874
+ tl.className = 'toolline';
124875
+ tl.innerHTML = toolContent(cell);
124876
+ contentTd.appendChild(tl);
124877
+ } else {
124878
+ var sum = document.createElement('div');
124879
+ sum.className = 'summary';
124880
+ sum.textContent = cell.text;
124881
+ contentTd.appendChild(sum);
124882
+ var facts = document.createElement('span');
124883
+ facts.className = 'facts';
124884
+ var f = [];
124885
+ if (cell.timeSeconds !== null && cell.timeSeconds !== undefined) f.push(fmtSeconds(cell.timeSeconds));
124886
+ f = f.concat(timingFacts(cell));
124887
+ if (cell.input !== undefined) f.push('in ' + cell.input);
124888
+ if (cell.cacheRead) f.push('read ' + cell.cacheRead);
124889
+ if (cell.cacheWrite) f.push('write ' + cell.cacheWrite);
124890
+ if (cell.output !== undefined) f.push('out ' + cell.output);
124891
+ if (f.length) facts.textContent = '· ' + f.join(' · ');
124892
+ contentTd.appendChild(facts);
124893
+ }
124894
+ row.appendChild(eventTd); row.appendChild(contentTd);
124895
+ (function (idx, el) { el.addEventListener('click', function () { showDetail(idx); }); })(i2, row);
124896
+ tbody.appendChild(row);
124897
+ rowEls[i2] = row;
124898
+ shown++;
124899
+ lastTurn = turn;
124900
+ }
124901
+ if (!shown) tbody.innerHTML = '<tr><td colspan="2"><div class="placeholder">无匹配记录</div></td></tr>';
124902
+ document.getElementById('count').textContent = shown + ' 条';
124903
+ }
124904
+ if (searchInput) searchInput.addEventListener('input', render);
124905
+ if (turnsBtn) turnsBtn.addEventListener('click', function () { collapsedTurns = !collapsedTurns; turnsBtn.classList.toggle('on', collapsedTurns); render(); });
124906
+ if (callsBtn) callsBtn.addEventListener('click', function () { collapsedCalls = !collapsedCalls; callsBtn.classList.toggle('on', collapsedCalls); render(); });
124907
+ if (modeBtn) modeBtn.addEventListener('click', function () { timeMode = !timeMode; modeBtn.textContent = timeMode ? 'Time' : 'Seq'; modeBtn.classList.toggle('on', timeMode); render(); });
124908
+ if (jsonBtn) jsonBtn.addEventListener('click', function () {
124909
+ var blob = new Blob([JSON.stringify({ cells: cells }, null, 2)], { type: 'application/json' });
124910
+ var url = URL.createObjectURL(blob);
124911
+ var a = document.createElement('a');
124912
+ a.href = url;
124913
+ a.download = 'scream-trace.json';
124914
+ a.click();
124915
+ URL.revokeObjectURL(url);
124916
+ });
124917
+ // Timeline navigation: wheel or drag over the strip scrolls the ledger and
124918
+ // positions the view at the corresponding rows.
124919
+ var timelineEl = timeline.parentElement;
124920
+ timelineEl.addEventListener('wheel', function (e) {
124921
+ if (!tablePane) return;
124922
+ e.preventDefault();
124923
+ tablePane.scrollTop += e.deltaY * 3;
124924
+ }, { passive: false });
124925
+ var dragStartY = null, dragStartScroll = 0;
124926
+ timelineEl.addEventListener('mousedown', function (e) {
124927
+ dragStartY = e.clientY;
124928
+ dragStartScroll = tablePane ? tablePane.scrollTop : 0;
124929
+ });
124930
+ window.addEventListener('mousemove', function (e) {
124931
+ if (dragStartY === null || !tablePane) return;
124932
+ tablePane.scrollTop = dragStartScroll + (dragStartY - e.clientY) * 3;
124933
+ });
124934
+ window.addEventListener('mouseup', function () { dragStartY = null; });
124935
+ // Draggable locator: drag or click on the strip to jump to a row.
124936
+ var locDrag = false;
124937
+ function locateAt(clientX) {
124938
+ var trackRect = track.getBoundingClientRect();
124939
+ var p = Math.min(1, Math.max(0, (clientX - trackRect.left) / trackRect.width));
124940
+ // The locator lives in .timeline (outside the cleared track); offset by the track origin.
124941
+ locator.style.left = (trackRect.left - timelineRectLeft() + p * trackRect.width - 1) + 'px';
124942
+ var n = currentFiltered.length;
124943
+ if (n < 2) return;
124944
+ var idx = Math.round(p * (n - 1));
124945
+ if (rowEls[idx] && rowEls[idx].scrollIntoView) rowEls[idx].scrollIntoView({ block: 'center' });
124946
+ }
124947
+ function timelineRectLeft() {
124948
+ return timeline.parentElement.getBoundingClientRect().left;
124949
+ }
124950
+ locator.addEventListener('mousedown', function (e) { e.stopPropagation(); e.preventDefault(); locDrag = true; });
124951
+ window.addEventListener('mousemove', function (e) {
124952
+ if (!locDrag) return;
124953
+ locateAt(e.clientX);
124954
+ });
124955
+ window.addEventListener('mouseup', function () { locDrag = false; });
124956
+ timelineEl.addEventListener('click', function (e) {
124957
+ if (e.target === locator) return;
124958
+ locateAt(e.clientX);
124959
+ });
124960
+ function syncLocatorFromTable() {
124961
+ if (!tablePane) return;
124962
+ var max = tablePane.scrollHeight - tablePane.clientHeight;
124963
+ var p = max > 0 ? tablePane.scrollTop / max : 0;
124964
+ var trackRect = track.getBoundingClientRect();
124965
+ locator.style.left = (trackRect.left - timelineRectLeft() + p * trackRect.width - 1) + 'px';
124966
+ }
124967
+ if (tablePane) tablePane.addEventListener('scroll', syncLocatorFromTable);
124968
+ render();
124969
+ syncLocatorFromTable();
124970
+ `;
124971
+ function escapeHtml(value) {
124972
+ return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;");
124973
+ }
124974
+ function renderTraceHtml(doc) {
124975
+ const dataJson = JSON.stringify(doc.cells).replaceAll("</", "<\\/");
124976
+ const meta = `${escapeHtml(doc.sessionId)} · ${new Date(doc.createdAt).toLocaleString()}`;
124977
+ return `<!DOCTYPE html>
124978
+ <html lang="zh">
124979
+ <head>
124980
+ <meta charset="utf-8">
124981
+ <meta name="viewport" content="width=device-width, initial-scale=1">
124982
+ <title>${escapeHtml(doc.title)} — 会话轨迹</title>
124983
+ <style>${CSS}</style>
124984
+ </head>
124985
+ <body>
124986
+ <div id="root">
124987
+ <div class="toolbar">
124988
+ <span class="title">${escapeHtml(doc.title)}</span>
124989
+ <span class="count" id="count"></span>
124990
+ <span class="count">${meta}</span>
124991
+ <button class="btn" id="turns">Turns</button>
124992
+ <button class="btn" id="calls">Calls</button>
124993
+ <button class="btn" id="mode">Seq</button>
124994
+ <button class="btn" id="json">JSON</button>
124995
+ <div class="search"><input id="q" type="search" placeholder="搜索…"></div>
124996
+ </div>
124997
+ <div class="timeline">
124998
+ <span class="lane-label" style="top:2px">Input</span>
124999
+ <span class="lane-label" style="top:16px">Model</span>
125000
+ <span class="lane-label" style="top:30px">Tools</span>
125001
+ <div class="track" id="timeline-track"></div>
125002
+ <div class="locator" id="locator"></div>
125003
+ </div>
125004
+ <div class="split">
125005
+ <div class="tablePane">
125006
+ <table>
125007
+ <colgroup><col class="event-column"><col></colgroup>
125008
+ <tbody id="rows"></tbody>
125009
+ </table>
125010
+ </div>
125011
+ <aside class="detail hidden" id="detail">
125012
+ <div class="dhead"><span class="dname mono" id="dname"></span>
125013
+ <button class="dclose" onclick="hideDetail()">×</button></div>
125014
+ <div class="dbody" id="dbody"></div>
125015
+ </aside>
125016
+ </div>
125017
+ </div>
125018
+ <script id="data" type="application/json">${dataJson}<\/script>
125019
+ <script>${RENDER_JS}<\/script>
125020
+ <div class="tip" id="tip"></div>
125021
+ </body>
125022
+ </html>`;
125023
+ }
125024
+ //#endregion
125025
+ //#region src/tui/commands/trace.ts
125026
+ /**
125027
+ * `/trace` — snapshot the current session's trajectory as a self-contained
125028
+ * interactive HTML document and open it in the browser. The file is written
125029
+ * to the OS temp dir (never the desktop / project), so repeated invocations
125030
+ * do not accumulate artifacts.
125031
+ */
125032
+ function handleTraceCommand(host) {
125033
+ runTrace(host);
125034
+ }
125035
+ async function runTrace(host) {
125036
+ try {
125037
+ const session = host.session;
125038
+ const sessionDir = session?.summary?.sessionDir;
125039
+ if (!sessionDir) {
125040
+ host.showError("当前会话不可用,无法导出轨迹");
125041
+ return;
125042
+ }
125043
+ const wirePath = join(sessionDir, "agents", "main", "wire.jsonl");
125044
+ if (!existsSync(wirePath)) {
125045
+ host.showError(`未找到轨迹文件: ${wirePath}`);
125046
+ return;
125047
+ }
125048
+ const cells = buildTraceCells({ wirePath });
125049
+ const html = renderTraceHtml({
125050
+ title: session?.summary?.title ?? host.state.appState.sessionTitle ?? "session",
125051
+ sessionId: session?.id ?? "unknown",
125052
+ createdAt: Date.now(),
125053
+ cells
125054
+ });
125055
+ const filePath = join(tmpdir(), "scream-trace.html");
125056
+ writeFileSync(filePath, html, "utf8");
125057
+ const opened = await openInBrowser(filePath);
125058
+ host.showStatus(opened ? "轨迹已打开" : "轨迹已生成,请手动打开");
125059
+ } catch (error) {
125060
+ host.showError(`轨迹导出失败: ${error instanceof Error ? error.message : String(error)}`);
125061
+ }
125062
+ }
125063
+ function openInBrowser(filePath) {
125064
+ const url = `file://${filePath}?v=${Date.now()}`;
125065
+ let command;
125066
+ let args;
125067
+ if (process.platform === "darwin") {
125068
+ command = "open";
125069
+ args = [url];
125070
+ } else if (process.platform === "win32") {
125071
+ command = "cmd";
125072
+ args = [
125073
+ "/c",
125074
+ "start",
125075
+ "",
125076
+ url
125077
+ ];
125078
+ } else {
125079
+ command = "xdg-open";
125080
+ args = [url];
125081
+ }
125082
+ return new Promise((resolve) => {
125083
+ const child = spawn(command, args, {
125084
+ stdio: "ignore",
125085
+ detached: true
125086
+ });
125087
+ child.on("error", () => resolve(false));
125088
+ child.on("spawn", () => resolve(true));
125089
+ });
125090
+ }
125091
+ //#endregion
124043
125092
  //#region src/tui/components/dialogs/editor-selector.ts
124044
125093
  function getEditorOptions() {
124045
125094
  return [
@@ -125086,10 +126135,10 @@ var FooterComponent = class {
125086
126135
  const totalInput = sessionUsage.inputCacheRead + sessionUsage.inputCacheCreation + sessionUsage.inputOther;
125087
126136
  const hitRatePct = totalInput > 0 ? sessionUsage.inputCacheRead / totalInput * 100 : void 0;
125088
126137
  const hitColor = hitRatePct !== void 0 && hitRatePct >= 90 ? colors.success : colors.textDim;
125089
- const segHit = chalk.hex(hitColor)(`${t("footer.hit")}: ${hitRatePct === void 0 ? "--" : `${hitRatePct.toFixed(2)}%`}`);
126138
+ const segHit = chalk.hex(colors.textDim)(`${t("footer.hit")}:`) + " " + chalk.hex(hitColor)(hitRatePct === void 0 ? "--" : `${hitRatePct.toFixed(2)}%`);
125090
126139
  const contextColor = pickContextColor(state.contextUsage, colors);
125091
126140
  const contextBarWidth = width >= 68 ? CONTEXT_BAR_WIDTH : width >= 52 ? 6 : 0;
125092
- rightText = `${ccDot} ${chalk.hex(contextColor)(formatContextStatus(state.contextUsage, state.contextTokens, state.maxContextTokens, contextBarWidth))} ${segHit} ${chalk.hex(colors.textDim)( ${statusLine}`)}`;
126141
+ rightText = `${ccDot} ${segHit} ${chalk.hex(contextColor)(formatContextStatus(state.contextUsage, state.contextTokens, state.maxContextTokens, contextBarWidth))} ${chalk.hex(colors.textDim)(` ${statusLine}`)}`;
125093
126142
  }
125094
126143
  const rightWidth = visibleWidth(rightText);
125095
126144
  const gap = 3;
@@ -127393,7 +128442,7 @@ async function guidedGoalSetup(host) {
127393
128442
  host.showNotice(t("goal.storm_breaker"), t("goal.conflict_loop"));
127394
128443
  return;
127395
128444
  }
127396
- const { TextInputDialogComponent } = await import("./text-input-dialog-Dfg978Sj.mjs");
128445
+ const { TextInputDialogComponent } = await import("./text-input-dialog-CYs9xQZi.mjs");
127397
128446
  const initialDesc = await promptText(host, TextInputDialogComponent, {
127398
128447
  title: t("goal.setup_title_initial"),
127399
128448
  subtitle: t("goal.setup_desc_hint"),
@@ -127414,7 +128463,7 @@ async function guidedGoalSetup(host) {
127414
128463
  await showGoalConfigWizard(host, session, confirmed.trim() || objective, false);
127415
128464
  }
127416
128465
  async function showGoalConfigWizard(host, session, objective, replace) {
127417
- const { TextInputDialogComponent } = await import("./text-input-dialog-Dfg978Sj.mjs");
128466
+ const { TextInputDialogComponent } = await import("./text-input-dialog-CYs9xQZi.mjs");
127418
128467
  const turnInput = await promptNumber(host, TextInputDialogComponent, {
127419
128468
  title: t("goal.wizard_title", { objective }),
127420
128469
  subtitle: t("goal.budget_turns_hint"),
@@ -136758,6 +137807,12 @@ async function handleBuiltInSlashCommand(host, name, args) {
136758
137807
  case "logout":
136759
137808
  await handleLogoutCommand(host);
136760
137809
  return;
137810
+ case "search":
137811
+ handleSearchCommand(host);
137812
+ return;
137813
+ case "trace":
137814
+ handleTraceCommand(host);
137815
+ return;
136761
137816
  case "eval":
136762
137817
  runEvalCommand(host);
136763
137818
  return;
@@ -136776,4 +137831,4 @@ async function handleBuiltInSlashCommand(host, name, args) {
136776
137831
  }
136777
137832
  }
136778
137833
  //#endregion
136779
- export { toTerminalHyperlink as $, stringValue as $t, highlightLines as A, DEFAULT_CATALOG_URL as An, ENABLE_TERMINAL_THEME_REPORTING as At, AssistantMessageComponent as B, isScreamError as Bn, isBusy as Bt, UserMessageComponent as C, getInputHistoryFile as Cn, contrastTextHex as Ct, ToolCallComponent as D, CLI_UI_MODE as Dn, DISABLE_TERMINAL_FOCUS_REPORTING as Dt, toggleEmptySessionHint as E, CLI_COMMAND_NAME as En, parseOsc11BackgroundTheme as Et, getSharedSpeedTracker as F, resolveScreamHome as Fn, QUERY_TERMINAL_THEME as Ft, resetBreathingClock as G, printableChar as Gt, WelcomeComponent as H, ErrorCodes as Hn, FooterComponent as Ht, SkillActivationComponent as I, MemoryMemoStore as In, TERMINAL_FOCUS_IN as It, handleExportDebugZipCommand as J, argsRecord as Jt, clearGoalState as K, STATUS_BULLET as Kt, ReadGroupComponent as L, flushDiagnosticLogs as Ln, TERMINAL_FOCUS_OUT as Lt, CachedContainer as M, saveCatalogCache as Mn, OSC11_RESPONSE as Mt, ThinkingComponent as N, ScreamHarness as Nn, OSC11_RESPONSE_PREFIX as Nt, renderDiffLines as O, CLI_USER_AGENT_PRODUCT as On, DISABLE_TERMINAL_THEME_REPORTING as Ot, estimateTokens as P, MCP_OAUTH_AUTHORIZATION_URL_TOOL_UPDATE as Pn, OSC11_RESPONSE_PREFIX_NO_ESC as Pt, handleTitleCommand as Q, serializeToolResultOutput as Qt, parseReadGroupOutput as R, log as Rn, TERMINAL_THEME_DARK as Rt, handleRevokeCommand as S, getDataDir as Sn, createThemeStyles as St, isTurnElapsedEnabled as T, detectInstallSource as Tn, detectTerminalTheme as Tt, BREATHE_CYCLE_MS as U, SCREAM_ERROR_INFO as Un, handleConnectCommand as Ut, AgentGroupComponent as V, isOrphanedToolCallError as Vn, isStreaming as Vt, getBreathingFrame as W, handleLogoutCommand as Wt, handleForkCommand as X, isTodoItemShape as Xt, handleExportMdCommand as Y, formatErrorMessage as Yt, handleInitCommand as Z, parseStreamingArgs as Zt, readUpdateCache as _, TuiConfigParseError as _n, showStatusReport as _t, handleSkillCommand as a, TIP_ROTATION_INTERVAL_MS as an, handleFusionPlanCommand as at, handleCcCommand as b, saveTuiConfig as bn, createEditorTheme as bt, isPlanExpandable as c, getLlmNotSetMessage as cn, handleThemeCommand as ct, handleMemoryCommand as d, BUILTIN_SLASH_COMMANDS as dn, showModelPicker as dt, truncateErrorMessage as en, changeThinkingLevel as et, handleChannelCommand as f, sortSlashCommands as fn, showPermissionPicker as ft, refreshUpdateCache as g, PULSE_WAVE_FRAMES as gn, clearInfoPanelState as gt, selectUpdateTarget as h, PIXEL_PULSE_FRAMES as hn, supportsBalance as ht, buildRoleAdditionalText as i, SESSION_TIPS as in, handleEditorCommand as it, langFromPath as j, fetchCatalog as jn, OSC11_QUERY as jt, renderDiffLinesClustered as k, PRODUCT_NAME as kn, ENABLE_TERMINAL_FOCUS_REPORTING as kt, MoonLoader as l, getNoActiveSessionMessage as ln, handleWolfpackCommand as lt, handleUpdateCommand as m, setExperimentalFlags as mn, refreshProviderBalance as mt, clearEvalPanelState as n, EXIT_CONFIRM_WINDOW_MS as nn, handleAutoCommand as nt, disposeChildren as o, getCtrlCHint as on, handleModelCommand as ot, handleMcpCommand as p, isExperimentalFlagEnabled as pn, showSettingsSelector as pt, refineGoal as q, appendStreamingArgsPreview as qt, openUrl as r, MAIN_AGENT_ID$1 as rn, handleCompactCommand as rt, hasDispose as s, getCtrlDHint as sn, handlePlanCommand as st, dispatchInput as t, EMPTY_SESSION_HINT_URL as tn, getModelCycleLevel as tt, formatMemoryMemoForInjection as u, buildSkillSlashCommands as un, handleYoloCommand as ut, appendJsonlLine as v, TuiLikePreferencesSchema as vn, showUsage as vt, isEmptySessionHintDismissed as w, getLogDir as wn, getColorPalette as wt, getDaemonInstructions as x, detectShellEnvironment as xn, createMarkdownTheme as xt, readJsonlFile as y, loadTuiConfig as yn, resolveThemeSync as yt, BackgroundAgentStatusComponent as z, resolveGlobalLogPath as zn, TERMINAL_THEME_LIGHT as zt };
137834
+ export { toTerminalHyperlink as $, parseStreamingArgs as $t, highlightLines as A, CLI_USER_AGENT_PRODUCT as An, ENABLE_TERMINAL_THEME_REPORTING as At, AssistantMessageComponent as B, log as Bn, isBusy as Bt, UserMessageComponent as C, detectShellEnvironment as Cn, contrastTextHex as Ct, ToolCallComponent as D, detectInstallSource as Dn, DISABLE_TERMINAL_FOCUS_REPORTING as Dt, toggleEmptySessionHint as E, getLogDir as En, parseOsc11BackgroundTheme as Et, getSharedSpeedTracker as F, ScreamHarness as Fn, QUERY_TERMINAL_THEME as Ft, resetBreathingClock as G, SCREAM_ERROR_INFO as Gn, handleConnectCommand as Gt, WelcomeComponent as H, isScreamError as Hn, FooterComponent as Ht, SkillActivationComponent as I, MCP_OAUTH_AUTHORIZATION_URL_TOOL_UPDATE as In, TERMINAL_FOCUS_IN as It, handleExportDebugZipCommand as J, STATUS_BULLET as Jt, clearGoalState as K, handleLogoutCommand as Kt, ReadGroupComponent as L, resolveScreamHome as Ln, TERMINAL_FOCUS_OUT as Lt, CachedContainer as M, DEFAULT_CATALOG_URL as Mn, OSC11_RESPONSE as Mt, ThinkingComponent as N, fetchCatalog as Nn, OSC11_RESPONSE_PREFIX as Nt, renderDiffLines as O, CLI_COMMAND_NAME as On, DISABLE_TERMINAL_THEME_REPORTING as Ot, estimateTokens as P, saveCatalogCache as Pn, OSC11_RESPONSE_PREFIX_NO_ESC as Pt, handleTitleCommand as Q, isTodoItemShape as Qt, parseReadGroupOutput as R, MemoryMemoStore as Rn, TERMINAL_THEME_DARK as Rt, handleRevokeCommand as S, saveTuiConfig as Sn, createThemeStyles as St, isTurnElapsedEnabled as T, getInputHistoryFile as Tn, detectTerminalTheme as Tt, BREATHE_CYCLE_MS as U, isOrphanedToolCallError as Un, handleTraceCommand as Ut, AgentGroupComponent as V, resolveGlobalLogPath as Vn, isStreaming as Vt, getBreathingFrame as W, ErrorCodes as Wn, handleSearchCommand as Wt, handleForkCommand as X, argsRecord as Xt, handleExportMdCommand as Y, appendStreamingArgsPreview as Yt, handleInitCommand as Z, formatErrorMessage as Zt, readUpdateCache as _, PIXEL_PULSE_FRAMES as _n, showStatusReport as _t, handleSkillCommand as a, MAIN_AGENT_ID$1 as an, handleFusionPlanCommand as at, handleCcCommand as b, TuiLikePreferencesSchema as bn, createEditorTheme as bt, isPlanExpandable as c, getCtrlCHint as cn, handleThemeCommand as ct, handleMemoryCommand as d, getNoActiveSessionMessage as dn, showModelPicker as dt, serializeToolResultOutput as en, changeThinkingLevel as et, handleChannelCommand as f, buildSkillSlashCommands as fn, showPermissionPicker as ft, refreshUpdateCache as g, setExperimentalFlags as gn, clearInfoPanelState as gt, selectUpdateTarget as h, isExperimentalFlagEnabled as hn, supportsBalance as ht, buildRoleAdditionalText as i, EXIT_CONFIRM_WINDOW_MS as in, handleEditorCommand as it, langFromPath as j, PRODUCT_NAME as jn, OSC11_QUERY as jt, renderDiffLinesClustered as k, CLI_UI_MODE as kn, ENABLE_TERMINAL_FOCUS_REPORTING as kt, MoonLoader as l, getCtrlDHint as ln, handleWolfpackCommand as lt, handleUpdateCommand as m, sortSlashCommands as mn, refreshProviderBalance as mt, clearEvalPanelState as n, truncateErrorMessage as nn, handleAutoCommand as nt, disposeChildren as o, SESSION_TIPS as on, handleModelCommand as ot, handleMcpCommand as p, BUILTIN_SLASH_COMMANDS as pn, showSettingsSelector as pt, refineGoal as q, printableChar as qt, openUrl as r, EMPTY_SESSION_HINT_URL as rn, handleCompactCommand as rt, hasDispose as s, TIP_ROTATION_INTERVAL_MS as sn, handlePlanCommand as st, dispatchInput as t, stringValue as tn, getModelCycleLevel as tt, formatMemoryMemoForInjection as u, getLlmNotSetMessage as un, handleYoloCommand as ut, appendJsonlLine as v, PULSE_WAVE_FRAMES as vn, showUsage as vt, isEmptySessionHintDismissed as w, getDataDir as wn, getColorPalette as wt, getDaemonInstructions as x, loadTuiConfig as xn, createMarkdownTheme as xt, readJsonlFile as y, TuiConfigParseError as yn, resolveThemeSync as yt, BackgroundAgentStatusComponent as z, flushDiagnosticLogs as zn, TERMINAL_THEME_LIGHT as zt };