@super-one/cli 0.75.2 → 0.75.3

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.
Files changed (3) hide show
  1. package/MANIFEST.json +2 -2
  2. package/lib/cli.mjs +2239 -757
  3. package/package.json +1 -1
package/lib/cli.mjs CHANGED
@@ -137,8 +137,8 @@ import { fileURLToPath } from "node:url";
137
137
  function resolveCliReleaseVersion() {
138
138
  const fromEnv = process.env.SUPERONE_CLI_VERSION?.trim();
139
139
  if (fromEnv) return fromEnv;
140
- if ("0.75.2".trim()) {
141
- return "0.75.2".trim();
140
+ if ("0.75.3".trim()) {
141
+ return "0.75.3".trim();
142
142
  }
143
143
  const fromDist = readDistManifestVersion();
144
144
  if (fromDist) return fromDist;
@@ -5329,12 +5329,14 @@ var init_session_messages = __esm({
5329
5329
  function desktopShowsSession(holders) {
5330
5330
  return holders.some((holder) => holder.startsWith(DESKTOP_WINDOW_HOLDER_PREFIX));
5331
5331
  }
5332
- var TRANSCRIPT_WINDOW_SCHEMA, TRANSCRIPT_WINDOW_METHOD, DESKTOP_WINDOW_HOLDER_PREFIX;
5332
+ var TRANSCRIPT_WINDOW_SCHEMA, TRANSCRIPT_WINDOW_METHOD, MAX_FOLD_FILES, TRANSCRIPT_FOLD_METHOD, DESKTOP_WINDOW_HOLDER_PREFIX;
5333
5333
  var init_transcript_window = __esm({
5334
5334
  "../../packages/shared/src/environment/transcript-window.ts"() {
5335
5335
  "use strict";
5336
5336
  TRANSCRIPT_WINDOW_SCHEMA = 1;
5337
5337
  TRANSCRIPT_WINDOW_METHOD = "session.transcriptWindow";
5338
+ MAX_FOLD_FILES = 100;
5339
+ TRANSCRIPT_FOLD_METHOD = "session.transcriptFold";
5338
5340
  DESKTOP_WINDOW_HOLDER_PREFIX = "desktop:";
5339
5341
  }
5340
5342
  });
@@ -8996,7 +8998,7 @@ var require_stream = __commonJS({
8996
8998
  callback();
8997
8999
  if (duplex._readableState.endEmitted) duplex.destroy();
8998
9000
  } else {
8999
- ws2._socket.once("finish", function finish() {
9001
+ ws2._socket.once("finish", function finish2() {
9000
9002
  callback();
9001
9003
  });
9002
9004
  ws2.close();
@@ -10433,6 +10435,16 @@ function resolveCodexCommandActions(item, cwdFallback) {
10433
10435
  return reads && reads[0]?.path === action.path ? reads : [action];
10434
10436
  });
10435
10437
  }
10438
+ function codexCommandPresentation(item, cwdFallback) {
10439
+ const actions = resolveCodexCommandActions(item, cwdFallback);
10440
+ const types = new Set(actions.map((action) => action.type));
10441
+ let kind = "bash";
10442
+ if (actions.length && actions.every((action) => ["read", "search", "listFiles"].includes(action.type))) {
10443
+ kind = types.size > 1 ? "explore" : types.has("read") ? "read" : types.has("search") ? "search" : "list";
10444
+ }
10445
+ const files = [...new Set(actions.filter((action) => action.type === "read" && action.path).map((action) => action.path))];
10446
+ return { kind, actions, files };
10447
+ }
10436
10448
  function parsedCommandFromBashInput(toolUseId, input, facts = {}) {
10437
10449
  if (!input.includes('"commandActions"')) return null;
10438
10450
  let params;
@@ -10453,6 +10465,10 @@ function parsedCommandFromBashInput(toolUseId, input, facts = {}) {
10453
10465
  status: facts.running ? "in_progress" : facts.isError || (facts.exitCode ?? 0) !== 0 ? "failed" : "completed"
10454
10466
  };
10455
10467
  }
10468
+ function isReadOnlyParsedCommand(toolUseId, input) {
10469
+ const item = parsedCommandFromBashInput(toolUseId, input);
10470
+ return item !== null && codexCommandPresentation(item).kind !== "bash";
10471
+ }
10456
10472
  var init_codex_command_actions = __esm({
10457
10473
  "../../packages/shared/src/codex-command-actions.ts"() {
10458
10474
  "use strict";
@@ -11652,6 +11668,387 @@ var init_session_message_range = __esm({
11652
11668
  }
11653
11669
  });
11654
11670
 
11671
+ // ../../packages/shared/src/codex-async-question.ts
11672
+ function isCodexAsyncAnswer(message) {
11673
+ return message.role === "user" && message.id.startsWith("codex_async_answer:");
11674
+ }
11675
+ function codexAsyncReplyText(message) {
11676
+ return message?.content.flatMap((block) => block.type === "text" ? [block.text] : []).join("\n") ?? null;
11677
+ }
11678
+ function isDismissedCodexAsyncAnswer(message, messages = []) {
11679
+ if (!isCodexAsyncAnswer(message)) return false;
11680
+ const reply = codexAsyncReplyText(message)?.trim();
11681
+ if (reply === CODEX_ASYNC_QUESTION_DISMISSED) return true;
11682
+ if (!reply) return false;
11683
+ const questions = codexAsyncAnswerQuestions(message, messages);
11684
+ return !!questions?.length && reply === formatCodexAsyncQuestionReply(questions, questions.map(() => CODEX_ASYNC_QUESTION_DISMISSED)).trim();
11685
+ }
11686
+ function codexAsyncQuestionRequest(item) {
11687
+ return {
11688
+ requestId: codexAsyncAnswerId(item.id),
11689
+ questions: (item.questions ?? []).map((question, index) => ({
11690
+ id: String(index),
11691
+ question: question.title,
11692
+ header: question.title,
11693
+ multiSelect: false,
11694
+ options: (question.options ?? []).map((label) => ({ label, description: "" }))
11695
+ }))
11696
+ };
11697
+ }
11698
+ function codexAsyncQuestionItems(message) {
11699
+ return readableContent(message).flatMap((block) => block.type === "text" && block.id && !block.parentToolUseId && block.codexAsyncQuestions?.length ? [{ id: block.id, type: "agent_message", text: block.text, delivery: "async", questions: block.codexAsyncQuestions }] : []);
11700
+ }
11701
+ function pendingCodexAsyncQuestions(messages) {
11702
+ const answered = new Set(messages.filter(isCodexAsyncAnswer).map((message) => message.id));
11703
+ const seen = /* @__PURE__ */ new Set();
11704
+ const pending3 = [];
11705
+ for (const message of messages) {
11706
+ if (message.role !== "assistant") continue;
11707
+ for (const item of codexAsyncQuestionItems(message)) {
11708
+ if (seen.has(item.id)) continue;
11709
+ seen.add(item.id);
11710
+ if (!answered.has(codexAsyncAnswerId(item.id))) pending3.push({ messageId: message.id, item, request: codexAsyncQuestionRequest(item) });
11711
+ }
11712
+ }
11713
+ return pending3;
11714
+ }
11715
+ function codexAsyncQuestionQueue(session) {
11716
+ const pending3 = session.pendingAsyncQuestions ?? pendingCodexAsyncQuestions(session.messages);
11717
+ const answered = new Set(session.messages.filter(isCodexAsyncAnswer).map((message) => message.id));
11718
+ return pending3.some((q2) => answered.has(q2.request.requestId)) ? pending3.filter((q2) => !answered.has(q2.request.requestId)) : pending3;
11719
+ }
11720
+ function codexAsyncAnswerQuestions(message, messages) {
11721
+ if (!isCodexAsyncAnswer(message)) return void 0;
11722
+ const stored = message.content.find((block) => block.type === "text" && block.codexAsyncQuestions?.length);
11723
+ if (stored?.type === "text") return stored.codexAsyncQuestions;
11724
+ const itemId = message.id.slice("codex_async_answer:".length);
11725
+ for (const source of messages) {
11726
+ const item = source.role === "assistant" ? codexAsyncQuestionItems(source).find((item2) => item2.id === itemId) : void 0;
11727
+ if (item) return item.questions;
11728
+ }
11729
+ return void 0;
11730
+ }
11731
+ function formatCodexAsyncQuestionReply(questions, answers) {
11732
+ if (questions.length === 1) return answers[0]?.trim() ?? "";
11733
+ return questions.map((question, index) => `${question.title}
11734
+ ${answers[index]?.trim() ?? ""}`).join("\n\n");
11735
+ }
11736
+ var codexAsyncAnswerId, CODEX_ASYNC_QUESTION_DISMISSED;
11737
+ var init_codex_async_question = __esm({
11738
+ "../../packages/shared/src/codex-async-question.ts"() {
11739
+ "use strict";
11740
+ init_codex_content();
11741
+ codexAsyncAnswerId = (itemId) => `codex_async_answer:${itemId}`;
11742
+ CODEX_ASYNC_QUESTION_DISMISSED = "[The user dismissed this question.]";
11743
+ }
11744
+ });
11745
+
11746
+ // ../../packages/shared/src/transcript-boundary.ts
11747
+ function contentKeys(content) {
11748
+ const counts = /* @__PURE__ */ new Map();
11749
+ return content.map((block) => {
11750
+ if (block.type === "notice" && block.fold) {
11751
+ for (const [kind2, count2] of Object.entries(block.fold.keyCounts ?? {})) counts.set(kind2, (counts.get(kind2) ?? 0) + count2);
11752
+ return block.fold.contentKey;
11753
+ }
11754
+ if (isToolUseBlock(block)) return `tool:${block.toolUseId}`;
11755
+ if (isToolResultBlock(block)) return `result:${block.toolUseId}`;
11756
+ const kind = contentKeyKind(block);
11757
+ const count = counts.get(kind) ?? 0;
11758
+ counts.set(kind, count + 1);
11759
+ return `${kind}:${count}`;
11760
+ });
11761
+ }
11762
+ function contentKeyKind(block) {
11763
+ const parent = "parentToolUseId" in block ? block.parentToolUseId ?? "" : "";
11764
+ return `${block.type}:${parent}`;
11765
+ }
11766
+ function contentKeySpan(content, keys, start, end) {
11767
+ const keyCounts = {};
11768
+ for (let i = start; i <= end; i++) {
11769
+ const block = content[i];
11770
+ if (isToolUseBlock(block) || isToolResultBlock(block)) continue;
11771
+ const kind = contentKeyKind(block);
11772
+ keyCounts[kind] = (keyCounts[kind] ?? 0) + 1;
11773
+ }
11774
+ return { contentKey: keys[start], ...Object.keys(keyCounts).length ? { keyCounts } : {} };
11775
+ }
11776
+ function blockText(block) {
11777
+ return block.type === "text" ? block.text : block.type === "thinking" ? block.thinking : void 0;
11778
+ }
11779
+ function itemText(item) {
11780
+ return "text" in item ? item.text : void 0;
11781
+ }
11782
+ function transcriptLengths(message) {
11783
+ const keys = contentKeys(message.content);
11784
+ return {
11785
+ content: Object.fromEntries(message.content.map((block, index) => [keys[index], blockText(block)?.length ?? -1])),
11786
+ items: Object.fromEntries((message.metadata?.codex?.items ?? []).map((item) => [item.id, itemText(item)?.length ?? -1]))
11787
+ };
11788
+ }
11789
+ function resolveTranscriptBoundaries(cuts, lengths) {
11790
+ let previous = { content: {}, items: {} };
11791
+ return cuts.map((cut) => {
11792
+ const cursor = cut.metadata.transcriptBoundary;
11793
+ const asyncAnswer = isCodexAsyncAnswer(cut);
11794
+ const resolved = { ...cursor, content: { ...previous.content }, items: { ...previous.items } };
11795
+ for (const kind of ["content", "items"]) {
11796
+ for (const [key, offset] of Object.entries(cursor[kind])) {
11797
+ const end = asyncAnswer ? lengths[kind][key] ?? offset : offset;
11798
+ resolved[kind][key] = Math.max(previous[kind][key] ?? -1, end);
11799
+ }
11800
+ }
11801
+ previous = resolved;
11802
+ return resolved;
11803
+ });
11804
+ }
11805
+ function captureTranscriptBoundary(message, messages = []) {
11806
+ let order = capturedOrders.get(message.id) ?? 0;
11807
+ for (const row2 of messages) {
11808
+ const cursor = row2.metadata?.transcriptBoundary;
11809
+ if (cursor?.messageId === message.id) order = Math.max(order, cursor.order);
11810
+ }
11811
+ order += 1;
11812
+ capturedOrders.delete(message.id);
11813
+ capturedOrders.set(message.id, order);
11814
+ if (capturedOrders.size > 1024) capturedOrders.delete(capturedOrders.keys().next().value);
11815
+ return {
11816
+ messageId: message.id,
11817
+ order,
11818
+ ...transcriptLengths(message)
11819
+ };
11820
+ }
11821
+ function anchorAsyncAnswer(message, messages) {
11822
+ if (!isCodexAsyncAnswer(message) || message.metadata?.transcriptBoundary) return message;
11823
+ const itemId = message.id.slice("codex_async_answer:".length);
11824
+ const source = messages.findLast((row2) => row2.status === "streaming" && row2.role === "assistant" && codexAsyncQuestionItems(row2).some((item) => item.id === itemId)) ?? messages.findLast((row2) => row2.status === "streaming" && row2.role === "assistant" && row2.providerId === "codex");
11825
+ return source ? { ...message, metadata: { ...message.metadata, transcriptBoundary: captureTranscriptBoundary(source, messages) } } : message;
11826
+ }
11827
+ var capturedOrders;
11828
+ var init_transcript_boundary = __esm({
11829
+ "../../packages/shared/src/transcript-boundary.ts"() {
11830
+ "use strict";
11831
+ init_codex_async_question();
11832
+ init_content_delta();
11833
+ capturedOrders = /* @__PURE__ */ new Map();
11834
+ }
11835
+ });
11836
+
11837
+ // ../../packages/shared/src/launch-options.ts
11838
+ var HARNESS_LAUNCH_OPTIONS;
11839
+ var init_launch_options = __esm({
11840
+ "../../packages/shared/src/launch-options.ts"() {
11841
+ "use strict";
11842
+ HARNESS_LAUNCH_OPTIONS = {
11843
+ claude: { permissionModes: ["default", "plan", "auto", "acceptEdits", "dontAsk", "bypassPermissions"], sandboxModes: ["off", "on", "auto"], defaultPermissionMode: "default" },
11844
+ codex: { permissionModes: ["default", "auto", "bypassPermissions"], sandboxModes: [], defaultPermissionMode: "default" },
11845
+ acp: { permissionModes: ["default", "plan", "auto", "bypassPermissions"], sandboxModes: [], defaultPermissionMode: "default" },
11846
+ // OpenCode selects native agents; permissions come from its own configuration.
11847
+ opencode: { permissionModes: [], sandboxModes: [], defaultPermissionMode: "default" },
11848
+ cursor: { permissionModes: ["agent", "plan", "bypassPermissions"], sandboxModes: ["off", "on"], defaultPermissionMode: "agent" },
11849
+ // Read-only first for display; dsh's own default preset is `workspace-write` (`default`).
11850
+ dsh: { permissionModes: ["plan", "default", "bypassPermissions"], sandboxModes: [], defaultPermissionMode: "default" }
11851
+ };
11852
+ }
11853
+ });
11854
+
11855
+ // ../../packages/shared/src/claude-fast-mode.ts
11856
+ function supportsClaudeFastMode(model, modelEnv) {
11857
+ return !Object.keys(modelEnv ?? {}).length && model?.supportsFastMode === true;
11858
+ }
11859
+ var init_claude_fast_mode = __esm({
11860
+ "../../packages/shared/src/claude-fast-mode.ts"() {
11861
+ "use strict";
11862
+ }
11863
+ });
11864
+
11865
+ // ../../packages/shared/src/codex-fast-mode.ts
11866
+ function findCodexFastServiceTier(model) {
11867
+ return model?.serviceTiers?.find((tier) => tier.id === "fast" || tier.id === "priority" || tier.name.trim().toLowerCase() === "fast");
11868
+ }
11869
+ var init_codex_fast_mode = __esm({
11870
+ "../../packages/shared/src/codex-fast-mode.ts"() {
11871
+ "use strict";
11872
+ }
11873
+ });
11874
+
11875
+ // ../../packages/shared/src/suggested-task-launch.ts
11876
+ function suggestedTaskSettings(settings) {
11877
+ return Object.fromEntries(SUGGESTED_TASK_SETTING_KEYS.flatMap((key) => settings[key] === void 0 ? [] : [[key, settings[key]]]));
11878
+ }
11879
+ function suggestedTaskRunSettings(profile, settings, codexFast = true) {
11880
+ const picked = suggestedTaskSettings(settings);
11881
+ const model = profile.models.find((model2) => model2.id === (picked.model ?? profile.defaultConfig.model));
11882
+ const modelEnv = profile.apiProviders.find((provider2) => provider2.id === (picked.apiProviderId ?? profile.defaultConfig.apiProviderId))?.modelEnv;
11883
+ if (profile.harnessId !== "codex" || !codexFast || !findCodexFastServiceTier(model)) delete picked.fastMode;
11884
+ if (profile.harnessId !== "claude" || !supportsClaudeFastMode(model, modelEnv)) delete picked.claudeFastMode;
11885
+ if (picked.effort && profile.efforts.length && !profile.efforts.includes(picked.effort)) delete picked.effort;
11886
+ return picked;
11887
+ }
11888
+ function suggestedTaskInitialChoice(profiles, providerId, settings) {
11889
+ const own = profiles.find((profile) => profile.id === providerId);
11890
+ if (!own) return profiles[0] ? { agentId: profiles[0].id, settings: {} } : null;
11891
+ const picked = suggestedTaskSettings(settings);
11892
+ if (picked.apiProviderId && !own.apiProviders.some((provider2) => provider2.id === picked.apiProviderId)) delete picked.apiProviderId;
11893
+ return { agentId: own.id, settings: picked };
11894
+ }
11895
+ function suggestedTaskBranchName(title2, taskId) {
11896
+ const slug = title2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40).replace(/-+$/, "");
11897
+ const id = taskId.replace(/[^a-z0-9]/gi, "").slice(0, 8);
11898
+ return `task/${slug ? `${slug}-` : ""}${id}`;
11899
+ }
11900
+ function parseSuggestedTaskChoice(value) {
11901
+ const invalid11 = (message) => {
11902
+ throw Object.assign(new Error(message), { code: "invalid_argument" });
11903
+ };
11904
+ if (value === void 0) return void 0;
11905
+ if (!value || typeof value !== "object" || Array.isArray(value)) return invalid11("invalid task launch choice");
11906
+ const { agentId, settings } = value;
11907
+ if (typeof agentId !== "string" || !agentId.trim() || !settings || typeof settings !== "object" || Array.isArray(settings)) return invalid11("task launch needs an agent and settings");
11908
+ const input = settings;
11909
+ const picked = {};
11910
+ for (const key of SUGGESTED_TASK_SETTING_KEYS) {
11911
+ const entry3 = input[key];
11912
+ if (entry3 === void 0) continue;
11913
+ const valid = key === "fastMode" || key === "claudeFastMode" ? typeof entry3 === "boolean" : key === "apiProviderId" && entry3 === null || typeof entry3 === "string";
11914
+ if (!valid) return invalid11(`invalid task launch ${key}`);
11915
+ if (key === "permissionMode" && !Object.values(HARNESS_LAUNCH_OPTIONS).some((option) => option.permissionModes.some((mode) => mode === entry3))) return invalid11("invalid permission mode");
11916
+ if (key === "sandboxMode" && !Object.values(HARNESS_LAUNCH_OPTIONS).some((option) => option.sandboxModes.some((mode) => mode === entry3))) return invalid11("invalid sandbox mode");
11917
+ Object.assign(picked, { [key]: entry3 });
11918
+ }
11919
+ return { agentId, settings: picked };
11920
+ }
11921
+ var SUGGESTED_TASK_SETTING_KEYS;
11922
+ var init_suggested_task_launch = __esm({
11923
+ "../../packages/shared/src/suggested-task-launch.ts"() {
11924
+ "use strict";
11925
+ init_launch_options();
11926
+ init_claude_fast_mode();
11927
+ init_codex_fast_mode();
11928
+ SUGGESTED_TASK_SETTING_KEYS = ["model", "effort", "apiProviderId", "permissionMode", "sandboxMode", "fastMode", "claudeFastMode"];
11929
+ }
11930
+ });
11931
+
11932
+ // ../../packages/shared/src/suggested-task.ts
11933
+ function record5(value) {
11934
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
11935
+ }
11936
+ function isSuggestTaskTool(toolName) {
11937
+ if (typeof toolName !== "string") return false;
11938
+ const mcp = parseMcpToolName(toolName);
11939
+ return mcp?.serverName === "superone" && mcp.mcpToolName === SUGGEST_TASK_TOOL_NAME;
11940
+ }
11941
+ function parseInput2(raw) {
11942
+ let value = raw;
11943
+ if (typeof raw === "string") {
11944
+ try {
11945
+ value = JSON.parse(raw);
11946
+ } catch {
11947
+ return null;
11948
+ }
11949
+ }
11950
+ const input = record5(value);
11951
+ const title2 = typeof input.title === "string" ? input.title.trim() : "";
11952
+ const prompt = typeof input.prompt === "string" ? input.prompt.trim() : "";
11953
+ if (!title2 || !prompt) return null;
11954
+ const cwd = typeof input.cwd === "string" && input.cwd.trim() ? input.cwd.trim() : void 0;
11955
+ return { title: title2, tldr: typeof input.tldr === "string" ? input.tldr.trim() : "", prompt, ...cwd ? { cwd } : {} };
11956
+ }
11957
+ function contentOf(message) {
11958
+ const value = record5(message);
11959
+ return readableContent({ content: Array.isArray(value.content) ? value.content : [], metadata: value.metadata }).map(record5);
11960
+ }
11961
+ function locateToolUse(messages, toolUseId) {
11962
+ for (let messageIndex = messages.length - 1; messageIndex >= 0; messageIndex--) {
11963
+ const use = contentOf(messages[messageIndex]).find((row2) => row2.type === "tool_use" && row2.toolUseId === toolUseId);
11964
+ if (use) return isSuggestTaskTool(use.toolName) ? { messageIndex, rowId: String(use.toolUseId), row: use } : null;
11965
+ }
11966
+ return null;
11967
+ }
11968
+ function locate(messages, taskId) {
11969
+ if (!taskId) return null;
11970
+ for (let messageIndex = messages.length - 1; messageIndex >= 0; messageIndex--) {
11971
+ const message = record5(messages[messageIndex]);
11972
+ for (const block of contentOf(message)) {
11973
+ if (block.type !== "tool_result" || typeof block.summary !== "string" || !block.summary.includes(taskId)) continue;
11974
+ const use = locateToolUse(messages, block.toolUseId);
11975
+ if (use) return use;
11976
+ }
11977
+ }
11978
+ return null;
11979
+ }
11980
+ function findSuggestedTask(messages, taskId) {
11981
+ const found = locate(messages, taskId);
11982
+ if (!found) return null;
11983
+ const input = parseInput2(found.row.input);
11984
+ if (!input) return null;
11985
+ const state = found.row.suggestedTask;
11986
+ return { input, ...state ? { state } : {} };
11987
+ }
11988
+ function applySuggestedTaskUpdate(messages, taskId, state) {
11989
+ const found = locate(messages, taskId);
11990
+ if (!found || found.row.suggestedTask) return messages;
11991
+ const patch = (row2) => {
11992
+ const value = record5(row2);
11993
+ const matches = value.type === "tool_use" && value.toolUseId === found.rowId || value.type === "mcp_tool_call" && value.id === found.rowId;
11994
+ return matches ? { ...value, suggestedTask: state } : row2;
11995
+ };
11996
+ return messages.map((message, index) => {
11997
+ if (index !== found.messageIndex) return message;
11998
+ const value = record5(message);
11999
+ const metadata = record5(value.metadata);
12000
+ const codex = record5(metadata.codex);
12001
+ return {
12002
+ ...value,
12003
+ ...Array.isArray(value.content) ? { content: value.content.map(patch) } : {},
12004
+ ...Array.isArray(codex.items) ? { metadata: { ...metadata, codex: { ...codex, items: codex.items.map(patch) } } } : {}
12005
+ };
12006
+ });
12007
+ }
12008
+ var SUGGEST_TASK_TOOL_NAME;
12009
+ var init_suggested_task = __esm({
12010
+ "../../packages/shared/src/suggested-task.ts"() {
12011
+ "use strict";
12012
+ init_codex_content();
12013
+ init_tool_ui();
12014
+ init_suggested_task_launch();
12015
+ SUGGEST_TASK_TOOL_NAME = "session_suggest_task";
12016
+ }
12017
+ });
12018
+
12019
+ // ../../packages/shared/src/jev-run-result-shape.ts
12020
+ function isJevRunToolName(toolName) {
12021
+ if (!toolName) return false;
12022
+ return /(?:^|__)(?:browser|computer|device)_run$/.test(toolName);
12023
+ }
12024
+ function looksLikeJevRunResult(obj) {
12025
+ const status2 = obj.status;
12026
+ if (status2 !== "paused" && status2 !== "done" && status2 !== "aborted") return false;
12027
+ if (typeof obj.runId !== "string") return false;
12028
+ return Array.isArray(obj.since_last) || typeof obj.progress === "object" && obj.progress !== null || typeof obj.steps === "number";
12029
+ }
12030
+ var init_jev_run_result_shape = __esm({
12031
+ "../../packages/shared/src/jev-run-result-shape.ts"() {
12032
+ "use strict";
12033
+ }
12034
+ });
12035
+
12036
+ // ../../packages/chat-core/src/media-predicates.ts
12037
+ function isMediaGenerateVideoTool(toolName) {
12038
+ return toolName === MEDIA_GENERATE_VIDEO_TOOL;
12039
+ }
12040
+ function isMediaVideoStatusTool(toolName) {
12041
+ return toolName === MEDIA_VIDEO_STATUS_TOOL;
12042
+ }
12043
+ var MEDIA_GENERATE_VIDEO_TOOL, MEDIA_VIDEO_STATUS_TOOL;
12044
+ var init_media_predicates = __esm({
12045
+ "../../packages/chat-core/src/media-predicates.ts"() {
12046
+ "use strict";
12047
+ MEDIA_GENERATE_VIDEO_TOOL = "mcp__superone__media_generate_video";
12048
+ MEDIA_VIDEO_STATUS_TOOL = "mcp__superone__media_video_status";
12049
+ }
12050
+ });
12051
+
11655
12052
  // ../../packages/runtime/src/stream/delivery/transcript-access.ts
11656
12053
  function missingRow() {
11657
12054
  return Object.assign(new Error("transcript index out of range"), { code: "not_found" });
@@ -11665,7 +12062,8 @@ function arrayTranscript(messages) {
11665
12062
  if (!message) throw missingRow();
11666
12063
  return message;
11667
12064
  },
11668
- indexOf: (messageId) => (ids ??= new Map(messages.map((message, index) => [message.id, index]))).get(messageId) ?? -1
12065
+ indexOf: (messageId) => (ids ??= new Map(messages.map((message, index) => [message.id, index]))).get(messageId) ?? -1,
12066
+ boundaryMessages: () => messages.filter((message) => message.metadata?.transcriptBoundary)
11669
12067
  };
11670
12068
  }
11671
12069
  function sqliteTranscript(db, input) {
@@ -11678,6 +12076,7 @@ function sqliteTranscript(db, input) {
11678
12076
  const countBefore = db.prepare(`SELECT COUNT(*) AS count FROM ${table2} WHERE session_id = ? AND sort_order < ?`);
11679
12077
  const byIndex = /* @__PURE__ */ new Map();
11680
12078
  const idIndex = /* @__PURE__ */ new Map();
12079
+ let boundaries;
11681
12080
  return {
11682
12081
  count: total,
11683
12082
  parsed: () => byIndex.size,
@@ -11703,6 +12102,14 @@ function sqliteTranscript(db, input) {
11703
12102
  if (index >= total) return -1;
11704
12103
  idIndex.set(messageId, index);
11705
12104
  return index;
12105
+ },
12106
+ boundaryMessages() {
12107
+ if (!input.boundarySql) return [];
12108
+ if (!boundaries) {
12109
+ const rows = db.prepare(input.boundarySql).all?.(sessionId);
12110
+ boundaries = (rows ?? []).map((row2) => input.parse(row2));
12111
+ }
12112
+ return boundaries;
11706
12113
  }
11707
12114
  };
11708
12115
  }
@@ -11712,24 +12119,6 @@ var init_transcript_access = __esm({
11712
12119
  }
11713
12120
  });
11714
12121
 
11715
- // ../../packages/shared/src/launch-options.ts
11716
- var HARNESS_LAUNCH_OPTIONS;
11717
- var init_launch_options = __esm({
11718
- "../../packages/shared/src/launch-options.ts"() {
11719
- "use strict";
11720
- HARNESS_LAUNCH_OPTIONS = {
11721
- claude: { permissionModes: ["default", "plan", "auto", "acceptEdits", "dontAsk", "bypassPermissions"], sandboxModes: ["off", "on", "auto"], defaultPermissionMode: "default" },
11722
- codex: { permissionModes: ["default", "auto", "bypassPermissions"], sandboxModes: [], defaultPermissionMode: "default" },
11723
- acp: { permissionModes: ["default", "plan", "auto", "bypassPermissions"], sandboxModes: [], defaultPermissionMode: "default" },
11724
- // OpenCode selects native agents; permissions come from its own configuration.
11725
- opencode: { permissionModes: [], sandboxModes: [], defaultPermissionMode: "default" },
11726
- cursor: { permissionModes: ["agent", "plan", "bypassPermissions"], sandboxModes: ["off", "on"], defaultPermissionMode: "agent" },
11727
- // Read-only first for display; dsh's own default preset is `workspace-write` (`default`).
11728
- dsh: { permissionModes: ["plan", "default", "bypassPermissions"], sandboxModes: [], defaultPermissionMode: "default" }
11729
- };
11730
- }
11731
- });
11732
-
11733
12122
  // ../../packages/shared/src/window-layout.ts
11734
12123
  var WINDOW_LAYOUT_IPC_CHANNELS;
11735
12124
  var init_window_layout = __esm({
@@ -12438,6 +12827,7 @@ var init_agent_types = __esm({
12438
12827
  ENVIRONMENT_SEND_SESSION_MESSAGE: "environment:sendSessionMessage",
12439
12828
  /** Open a remote session in the chat at a node snapshot (`session.load`) and follow it. */
12440
12829
  ENVIRONMENT_OPEN_REMOTE_SESSION: "environment:openRemoteSession",
12830
+ ENVIRONMENT_LOAD_TRANSCRIPT_FOLD: "environment:loadTranscriptFold",
12441
12831
  ENVIRONMENT_SUBSCRIBE_DETAIL: "environment:subscribeDetail",
12442
12832
  ENVIRONMENT_UNSUBSCRIBE_DETAIL: "environment:unsubscribeDetail",
12443
12833
  ENVIRONMENT_INTERRUPT_SESSION: "environment:interruptSession",
@@ -12617,16 +13007,6 @@ var init_harness_sandbox = __esm({
12617
13007
  }
12618
13008
  });
12619
13009
 
12620
- // ../../packages/shared/src/codex-fast-mode.ts
12621
- function findCodexFastServiceTier(model) {
12622
- return model?.serviceTiers?.find((tier) => tier.id === "fast" || tier.id === "priority" || tier.name.trim().toLowerCase() === "fast");
12623
- }
12624
- var init_codex_fast_mode = __esm({
12625
- "../../packages/shared/src/codex-fast-mode.ts"() {
12626
- "use strict";
12627
- }
12628
- });
12629
-
12630
13010
  // ../../packages/shared/src/model-option-params.ts
12631
13011
  function isEffortCatalogParam(param) {
12632
13012
  if (param.id === "thinking" || /^thinking$/i.test(param.displayName ?? "")) return false;
@@ -14373,17 +14753,17 @@ function mapQuestionRequest(payload, fallbackId) {
14373
14753
  function mapPlanRequest(payload, fallbackId) {
14374
14754
  const interactionId = asString2(payload.interactionId) ?? asString2(payload.requestId) ?? fallbackId;
14375
14755
  const input = asRecord2(payload.input);
14376
- let planContent = asString2(payload.plan) ?? asString2(payload.planContent) ?? asString2(input.plan) ?? asString2(input.planContent) ?? "";
14377
- if (!planContent && input.plan && typeof input.plan === "object") {
14756
+ let planContent2 = asString2(payload.plan) ?? asString2(payload.planContent) ?? asString2(input.plan) ?? asString2(input.planContent) ?? "";
14757
+ if (!planContent2 && input.plan && typeof input.plan === "object") {
14378
14758
  try {
14379
- planContent = JSON.stringify(input.plan);
14759
+ planContent2 = JSON.stringify(input.plan);
14380
14760
  } catch {
14381
- planContent = "";
14761
+ planContent2 = "";
14382
14762
  }
14383
14763
  }
14384
14764
  return {
14385
14765
  requestId: interactionId,
14386
- planContent: planContent || "Plan approval required",
14766
+ planContent: planContent2 || "Plan approval required",
14387
14767
  planFilePath: asString2(payload.planFilePath) ?? asString2(input.planFilePath) ?? "",
14388
14768
  allowedPrompts: Array.isArray(payload.allowedPrompts) ? payload.allowedPrompts : Array.isArray(input.allowedPrompts) ? input.allowedPrompts : []
14389
14769
  };
@@ -19250,160 +19630,6 @@ var init_codex_metadata2 = __esm({
19250
19630
  }
19251
19631
  });
19252
19632
 
19253
- // ../../packages/shared/src/claude-fast-mode.ts
19254
- function supportsClaudeFastMode(model, modelEnv) {
19255
- return !Object.keys(modelEnv ?? {}).length && model?.supportsFastMode === true;
19256
- }
19257
- var init_claude_fast_mode = __esm({
19258
- "../../packages/shared/src/claude-fast-mode.ts"() {
19259
- "use strict";
19260
- }
19261
- });
19262
-
19263
- // ../../packages/shared/src/suggested-task-launch.ts
19264
- function suggestedTaskSettings(settings) {
19265
- return Object.fromEntries(SUGGESTED_TASK_SETTING_KEYS.flatMap((key) => settings[key] === void 0 ? [] : [[key, settings[key]]]));
19266
- }
19267
- function suggestedTaskRunSettings(profile, settings, codexFast = true) {
19268
- const picked = suggestedTaskSettings(settings);
19269
- const model = profile.models.find((model2) => model2.id === (picked.model ?? profile.defaultConfig.model));
19270
- const modelEnv = profile.apiProviders.find((provider2) => provider2.id === (picked.apiProviderId ?? profile.defaultConfig.apiProviderId))?.modelEnv;
19271
- if (profile.harnessId !== "codex" || !codexFast || !findCodexFastServiceTier(model)) delete picked.fastMode;
19272
- if (profile.harnessId !== "claude" || !supportsClaudeFastMode(model, modelEnv)) delete picked.claudeFastMode;
19273
- if (picked.effort && profile.efforts.length && !profile.efforts.includes(picked.effort)) delete picked.effort;
19274
- return picked;
19275
- }
19276
- function suggestedTaskInitialChoice(profiles, providerId, settings) {
19277
- const own = profiles.find((profile) => profile.id === providerId);
19278
- if (!own) return profiles[0] ? { agentId: profiles[0].id, settings: {} } : null;
19279
- const picked = suggestedTaskSettings(settings);
19280
- if (picked.apiProviderId && !own.apiProviders.some((provider2) => provider2.id === picked.apiProviderId)) delete picked.apiProviderId;
19281
- return { agentId: own.id, settings: picked };
19282
- }
19283
- function suggestedTaskBranchName(title2, taskId) {
19284
- const slug = title2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40).replace(/-+$/, "");
19285
- const id = taskId.replace(/[^a-z0-9]/gi, "").slice(0, 8);
19286
- return `task/${slug ? `${slug}-` : ""}${id}`;
19287
- }
19288
- function parseSuggestedTaskChoice(value) {
19289
- const invalid11 = (message) => {
19290
- throw Object.assign(new Error(message), { code: "invalid_argument" });
19291
- };
19292
- if (value === void 0) return void 0;
19293
- if (!value || typeof value !== "object" || Array.isArray(value)) return invalid11("invalid task launch choice");
19294
- const { agentId, settings } = value;
19295
- if (typeof agentId !== "string" || !agentId.trim() || !settings || typeof settings !== "object" || Array.isArray(settings)) return invalid11("task launch needs an agent and settings");
19296
- const input = settings;
19297
- const picked = {};
19298
- for (const key of SUGGESTED_TASK_SETTING_KEYS) {
19299
- const entry3 = input[key];
19300
- if (entry3 === void 0) continue;
19301
- const valid = key === "fastMode" || key === "claudeFastMode" ? typeof entry3 === "boolean" : key === "apiProviderId" && entry3 === null || typeof entry3 === "string";
19302
- if (!valid) return invalid11(`invalid task launch ${key}`);
19303
- if (key === "permissionMode" && !Object.values(HARNESS_LAUNCH_OPTIONS).some((option) => option.permissionModes.some((mode) => mode === entry3))) return invalid11("invalid permission mode");
19304
- if (key === "sandboxMode" && !Object.values(HARNESS_LAUNCH_OPTIONS).some((option) => option.sandboxModes.some((mode) => mode === entry3))) return invalid11("invalid sandbox mode");
19305
- Object.assign(picked, { [key]: entry3 });
19306
- }
19307
- return { agentId, settings: picked };
19308
- }
19309
- var SUGGESTED_TASK_SETTING_KEYS;
19310
- var init_suggested_task_launch = __esm({
19311
- "../../packages/shared/src/suggested-task-launch.ts"() {
19312
- "use strict";
19313
- init_launch_options();
19314
- init_claude_fast_mode();
19315
- init_codex_fast_mode();
19316
- SUGGESTED_TASK_SETTING_KEYS = ["model", "effort", "apiProviderId", "permissionMode", "sandboxMode", "fastMode", "claudeFastMode"];
19317
- }
19318
- });
19319
-
19320
- // ../../packages/shared/src/suggested-task.ts
19321
- function record5(value) {
19322
- return value && typeof value === "object" && !Array.isArray(value) ? value : {};
19323
- }
19324
- function isSuggestTaskTool(toolName) {
19325
- if (typeof toolName !== "string") return false;
19326
- const mcp = parseMcpToolName(toolName);
19327
- return mcp?.serverName === "superone" && mcp.mcpToolName === SUGGEST_TASK_TOOL_NAME;
19328
- }
19329
- function parseInput2(raw) {
19330
- let value = raw;
19331
- if (typeof raw === "string") {
19332
- try {
19333
- value = JSON.parse(raw);
19334
- } catch {
19335
- return null;
19336
- }
19337
- }
19338
- const input = record5(value);
19339
- const title2 = typeof input.title === "string" ? input.title.trim() : "";
19340
- const prompt = typeof input.prompt === "string" ? input.prompt.trim() : "";
19341
- if (!title2 || !prompt) return null;
19342
- const cwd = typeof input.cwd === "string" && input.cwd.trim() ? input.cwd.trim() : void 0;
19343
- return { title: title2, tldr: typeof input.tldr === "string" ? input.tldr.trim() : "", prompt, ...cwd ? { cwd } : {} };
19344
- }
19345
- function contentOf(message) {
19346
- const value = record5(message);
19347
- return readableContent({ content: Array.isArray(value.content) ? value.content : [], metadata: value.metadata }).map(record5);
19348
- }
19349
- function locateToolUse(messages, toolUseId) {
19350
- for (let messageIndex = messages.length - 1; messageIndex >= 0; messageIndex--) {
19351
- const use = contentOf(messages[messageIndex]).find((row2) => row2.type === "tool_use" && row2.toolUseId === toolUseId);
19352
- if (use) return isSuggestTaskTool(use.toolName) ? { messageIndex, rowId: String(use.toolUseId), row: use } : null;
19353
- }
19354
- return null;
19355
- }
19356
- function locate(messages, taskId) {
19357
- if (!taskId) return null;
19358
- for (let messageIndex = messages.length - 1; messageIndex >= 0; messageIndex--) {
19359
- const message = record5(messages[messageIndex]);
19360
- for (const block of contentOf(message)) {
19361
- if (block.type !== "tool_result" || typeof block.summary !== "string" || !block.summary.includes(taskId)) continue;
19362
- const use = locateToolUse(messages, block.toolUseId);
19363
- if (use) return use;
19364
- }
19365
- }
19366
- return null;
19367
- }
19368
- function findSuggestedTask(messages, taskId) {
19369
- const found = locate(messages, taskId);
19370
- if (!found) return null;
19371
- const input = parseInput2(found.row.input);
19372
- if (!input) return null;
19373
- const state = found.row.suggestedTask;
19374
- return { input, ...state ? { state } : {} };
19375
- }
19376
- function applySuggestedTaskUpdate(messages, taskId, state) {
19377
- const found = locate(messages, taskId);
19378
- if (!found || found.row.suggestedTask) return messages;
19379
- const patch = (row2) => {
19380
- const value = record5(row2);
19381
- const matches = value.type === "tool_use" && value.toolUseId === found.rowId || value.type === "mcp_tool_call" && value.id === found.rowId;
19382
- return matches ? { ...value, suggestedTask: state } : row2;
19383
- };
19384
- return messages.map((message, index) => {
19385
- if (index !== found.messageIndex) return message;
19386
- const value = record5(message);
19387
- const metadata = record5(value.metadata);
19388
- const codex = record5(metadata.codex);
19389
- return {
19390
- ...value,
19391
- ...Array.isArray(value.content) ? { content: value.content.map(patch) } : {},
19392
- ...Array.isArray(codex.items) ? { metadata: { ...metadata, codex: { ...codex, items: codex.items.map(patch) } } } : {}
19393
- };
19394
- });
19395
- }
19396
- var SUGGEST_TASK_TOOL_NAME;
19397
- var init_suggested_task = __esm({
19398
- "../../packages/shared/src/suggested-task.ts"() {
19399
- "use strict";
19400
- init_codex_content();
19401
- init_tool_ui();
19402
- init_suggested_task_launch();
19403
- SUGGEST_TASK_TOOL_NAME = "session_suggest_task";
19404
- }
19405
- });
19406
-
19407
19633
  // ../../packages/chat-core/src/ports.ts
19408
19634
  function createStreamingToolInputState() {
19409
19635
  return {
@@ -19456,81 +19682,6 @@ var init_ports = __esm({
19456
19682
  }
19457
19683
  });
19458
19684
 
19459
- // ../../packages/shared/src/codex-async-question.ts
19460
- function isCodexAsyncAnswer(message) {
19461
- return message.role === "user" && message.id.startsWith("codex_async_answer:");
19462
- }
19463
- function codexAsyncReplyText(message) {
19464
- return message?.content.flatMap((block) => block.type === "text" ? [block.text] : []).join("\n") ?? null;
19465
- }
19466
- function isDismissedCodexAsyncAnswer(message, messages = []) {
19467
- if (!isCodexAsyncAnswer(message)) return false;
19468
- const reply = codexAsyncReplyText(message)?.trim();
19469
- if (reply === CODEX_ASYNC_QUESTION_DISMISSED) return true;
19470
- if (!reply) return false;
19471
- const questions = codexAsyncAnswerQuestions(message, messages);
19472
- return !!questions?.length && reply === formatCodexAsyncQuestionReply(questions, questions.map(() => CODEX_ASYNC_QUESTION_DISMISSED)).trim();
19473
- }
19474
- function codexAsyncQuestionRequest(item) {
19475
- return {
19476
- requestId: codexAsyncAnswerId(item.id),
19477
- questions: (item.questions ?? []).map((question, index) => ({
19478
- id: String(index),
19479
- question: question.title,
19480
- header: question.title,
19481
- multiSelect: false,
19482
- options: (question.options ?? []).map((label) => ({ label, description: "" }))
19483
- }))
19484
- };
19485
- }
19486
- function codexAsyncQuestionItems(message) {
19487
- return readableContent(message).flatMap((block) => block.type === "text" && block.id && !block.parentToolUseId && block.codexAsyncQuestions?.length ? [{ id: block.id, type: "agent_message", text: block.text, delivery: "async", questions: block.codexAsyncQuestions }] : []);
19488
- }
19489
- function pendingCodexAsyncQuestions(messages) {
19490
- const answered = new Set(messages.filter(isCodexAsyncAnswer).map((message) => message.id));
19491
- const seen = /* @__PURE__ */ new Set();
19492
- const pending3 = [];
19493
- for (const message of messages) {
19494
- if (message.role !== "assistant") continue;
19495
- for (const item of codexAsyncQuestionItems(message)) {
19496
- if (seen.has(item.id)) continue;
19497
- seen.add(item.id);
19498
- if (!answered.has(codexAsyncAnswerId(item.id))) pending3.push({ messageId: message.id, item, request: codexAsyncQuestionRequest(item) });
19499
- }
19500
- }
19501
- return pending3;
19502
- }
19503
- function codexAsyncQuestionQueue(session) {
19504
- const pending3 = session.pendingAsyncQuestions ?? pendingCodexAsyncQuestions(session.messages);
19505
- const answered = new Set(session.messages.filter(isCodexAsyncAnswer).map((message) => message.id));
19506
- return pending3.some((q2) => answered.has(q2.request.requestId)) ? pending3.filter((q2) => !answered.has(q2.request.requestId)) : pending3;
19507
- }
19508
- function codexAsyncAnswerQuestions(message, messages) {
19509
- if (!isCodexAsyncAnswer(message)) return void 0;
19510
- const stored = message.content.find((block) => block.type === "text" && block.codexAsyncQuestions?.length);
19511
- if (stored?.type === "text") return stored.codexAsyncQuestions;
19512
- const itemId = message.id.slice("codex_async_answer:".length);
19513
- for (const source of messages) {
19514
- const item = source.role === "assistant" ? codexAsyncQuestionItems(source).find((item2) => item2.id === itemId) : void 0;
19515
- if (item) return item.questions;
19516
- }
19517
- return void 0;
19518
- }
19519
- function formatCodexAsyncQuestionReply(questions, answers) {
19520
- if (questions.length === 1) return answers[0]?.trim() ?? "";
19521
- return questions.map((question, index) => `${question.title}
19522
- ${answers[index]?.trim() ?? ""}`).join("\n\n");
19523
- }
19524
- var codexAsyncAnswerId, CODEX_ASYNC_QUESTION_DISMISSED;
19525
- var init_codex_async_question = __esm({
19526
- "../../packages/shared/src/codex-async-question.ts"() {
19527
- "use strict";
19528
- init_codex_content();
19529
- codexAsyncAnswerId = (itemId) => `codex_async_answer:${itemId}`;
19530
- CODEX_ASYNC_QUESTION_DISMISSED = "[The user dismissed this question.]";
19531
- }
19532
- });
19533
-
19534
19685
  // ../../packages/chat-core/src/codex.ts
19535
19686
  function reduceCodex(session, event, ports2 = defaultChatCorePorts) {
19536
19687
  switch (event.type) {
@@ -19674,22 +19825,6 @@ var init_transformers = __esm({
19674
19825
  }
19675
19826
  });
19676
19827
 
19677
- // ../../packages/chat-core/src/media-predicates.ts
19678
- function isMediaGenerateVideoTool(toolName) {
19679
- return toolName === MEDIA_GENERATE_VIDEO_TOOL;
19680
- }
19681
- function isMediaVideoStatusTool(toolName) {
19682
- return toolName === MEDIA_VIDEO_STATUS_TOOL;
19683
- }
19684
- var MEDIA_GENERATE_VIDEO_TOOL, MEDIA_VIDEO_STATUS_TOOL;
19685
- var init_media_predicates = __esm({
19686
- "../../packages/chat-core/src/media-predicates.ts"() {
19687
- "use strict";
19688
- MEDIA_GENERATE_VIDEO_TOOL = "mcp__superone__media_generate_video";
19689
- MEDIA_VIDEO_STATUS_TOOL = "mcp__superone__media_video_status";
19690
- }
19691
- });
19692
-
19693
19828
  // ../../packages/chat-core/src/host-workflow-card.ts
19694
19829
  function runIdFromSummary(summary2) {
19695
19830
  if (!summary2) return void 0;
@@ -19880,6 +20015,99 @@ function todoWriteTodos(input) {
19880
20015
  function todoListUpdate(session, todos) {
19881
20016
  return { todos, _nextTodoId: Object.keys(todos).length + 1, ...!session._todosUserDismissed && { showTodos: true } };
19882
20017
  }
20018
+ function applyTodoToolInput(session, toolName, input, resultToolTodos) {
20019
+ if (toolName === "TodoWrite") {
20020
+ const listed = todoWriteTodos(input);
20021
+ return listed ? todoListUpdate(session, listed) : null;
20022
+ }
20023
+ if (toolName === "TaskCreate") {
20024
+ const resolvedId = resultToolTodos?.[0]?.taskId;
20025
+ const id = resolvedId ?? String(session._nextTodoId);
20026
+ return {
20027
+ ...resolvedId ? {} : { _nextTodoId: session._nextTodoId + 1 },
20028
+ showTodos: !session._todosUserDismissed,
20029
+ todos: {
20030
+ ...session.todos,
20031
+ [id]: {
20032
+ id,
20033
+ subject: input.subject ?? "",
20034
+ description: input.description ?? "",
20035
+ status: "pending",
20036
+ activeForm: input.activeForm
20037
+ }
20038
+ }
20039
+ };
20040
+ }
20041
+ if (toolName === "TaskUpdate" && input.taskId) return mergeTaskUpdate(session, input.taskId, input);
20042
+ return null;
20043
+ }
20044
+ function applyTodoResult(session, delta) {
20045
+ const items = delta.toolTodos;
20046
+ const toolName = delta.todoToolName;
20047
+ if (!items || !toolName) return null;
20048
+ if (toolName === "TodoWrite") {
20049
+ return applyTodoToolInput(session, toolName, {
20050
+ todos: items.map((item2) => ({
20051
+ content: item2.subject ?? item2.content,
20052
+ description: item2.description,
20053
+ status: item2.status,
20054
+ activeForm: item2.activeForm
20055
+ }))
20056
+ });
20057
+ }
20058
+ const item = items[0];
20059
+ if (!item) return null;
20060
+ if (toolName === "TaskCreate") {
20061
+ return applyTodoToolInput(session, toolName, {
20062
+ subject: item.subject ?? item.content,
20063
+ description: item.description,
20064
+ activeForm: item.activeForm
20065
+ }, item.taskId ? [{ taskId: item.taskId }] : void 0);
20066
+ }
20067
+ if (toolName === "TaskUpdate") {
20068
+ return applyTodoToolInput(session, toolName, {
20069
+ taskId: item.taskId,
20070
+ status: item.status || void 0,
20071
+ subject: item.subject,
20072
+ description: item.description,
20073
+ activeForm: item.activeForm,
20074
+ owner: item.owner,
20075
+ addBlockedBy: item.addBlockedBy,
20076
+ addBlocks: item.addBlocks
20077
+ });
20078
+ }
20079
+ return null;
20080
+ }
20081
+ function mergeTaskUpdate(session, taskId, input) {
20082
+ const existing = session.todos[taskId];
20083
+ if (!existing) return null;
20084
+ if (input.status === "deleted") {
20085
+ const { [taskId]: _3, ...rest } = session.todos;
20086
+ return { todos: rest };
20087
+ }
20088
+ const mergeIds = (prev, add) => {
20089
+ if (!Array.isArray(add) || add.length === 0) return prev;
20090
+ return Array.from(/* @__PURE__ */ new Set([...prev ?? [], ...add.map(String)]));
20091
+ };
20092
+ const nextBlockedBy = mergeIds(existing.blockedBy, input.addBlockedBy);
20093
+ const nextBlocks = mergeIds(existing.blocks, input.addBlocks);
20094
+ return {
20095
+ ...!session._todosUserDismissed && { showTodos: true },
20096
+ todos: {
20097
+ ...session.todos,
20098
+ [taskId]: {
20099
+ ...existing,
20100
+ ...input.status && { status: input.status },
20101
+ ...input.subject && { subject: input.subject },
20102
+ ...input.description && { description: input.description },
20103
+ ...input.activeForm && { activeForm: input.activeForm },
20104
+ ...input.owner && { owner: input.owner },
20105
+ ...nextBlockedBy && { blockedBy: nextBlockedBy },
20106
+ ...nextBlocks && { blocks: nextBlocks }
20107
+ }
20108
+ }
20109
+ };
20110
+ }
19883
20111
  var init_todos = __esm({
19884
20112
  "../../packages/chat-core/src/todos.ts"() {
19885
20113
  "use strict";
@@ -19944,59 +20172,8 @@ function reduceContentDelta(session, event, ports2 = defaultChatCorePorts) {
19944
20172
  const tn2 = toolBlock.toolName;
19945
20173
  if (!resultDelta.isError && (tn2 === "TodoWrite" || tn2 === "TaskCreate" || tn2 === "TaskUpdate")) {
19946
20174
  try {
19947
- const input = JSON.parse(toolBlock.input);
19948
- const listed = tn2 === "TodoWrite" ? todoWriteTodos(input) : null;
19949
- if (listed) {
19950
- extraUpdates = todoListUpdate(session, listed);
19951
- } else if (tn2 === "TaskCreate") {
19952
- const resolvedId = resultDelta.toolTodos?.[0]?.taskId;
19953
- const id = resolvedId ?? String(session._nextTodoId);
19954
- extraUpdates = {
19955
- ...resolvedId ? {} : { _nextTodoId: session._nextTodoId + 1 },
19956
- showTodos: !session._todosUserDismissed,
19957
- todos: {
19958
- ...session.todos,
19959
- [id]: {
19960
- id,
19961
- subject: input.subject ?? "",
19962
- description: input.description ?? "",
19963
- status: "pending",
19964
- activeForm: input.activeForm
19965
- }
19966
- }
19967
- };
19968
- } else if (tn2 === "TaskUpdate" && input.taskId) {
19969
- const existing = session.todos[input.taskId];
19970
- if (existing) {
19971
- if (input.status === "deleted") {
19972
- const { [input.taskId]: _3, ...rest } = session.todos;
19973
- extraUpdates = { todos: rest };
19974
- } else {
19975
- const mergeIds = (prev, add) => {
19976
- if (!Array.isArray(add) || add.length === 0) return prev;
19977
- return Array.from(/* @__PURE__ */ new Set([...prev ?? [], ...add.map(String)]));
19978
- };
19979
- const nextBlockedBy = mergeIds(existing.blockedBy, input.addBlockedBy);
19980
- const nextBlocks = mergeIds(existing.blocks, input.addBlocks);
19981
- extraUpdates = {
19982
- ...!session._todosUserDismissed && { showTodos: true },
19983
- todos: {
19984
- ...session.todos,
19985
- [input.taskId]: {
19986
- ...existing,
19987
- ...input.status && { status: input.status },
19988
- ...input.subject && { subject: input.subject },
19989
- ...input.description && { description: input.description },
19990
- ...input.activeForm && { activeForm: input.activeForm },
19991
- ...input.owner && { owner: input.owner },
19992
- ...nextBlockedBy && { blockedBy: nextBlockedBy },
19993
- ...nextBlocks && { blocks: nextBlocks }
19994
- }
19995
- }
19996
- };
19997
- }
19998
- }
19999
- }
20175
+ const applied = applyTodoToolInput(session, tn2, JSON.parse(toolBlock.input), resultDelta.toolTodos);
20176
+ if (applied) extraUpdates = applied;
20000
20177
  } catch {
20001
20178
  }
20002
20179
  }
@@ -20075,6 +20252,14 @@ function reduceContentDelta(session, event, ports2 = defaultChatCorePorts) {
20075
20252
  const stripped = dropHostWorkflowShadow(updatedMessages, resultDelta.toolUseId, resultDelta.summary);
20076
20253
  if (stripped) updatedMessages = stripped;
20077
20254
  }
20255
+ if (event.delta.type === "todo_result") {
20256
+ const resultDelta = event.delta;
20257
+ ports2.streaming.clear(resultDelta.toolUseId);
20258
+ const restPreviews = dropStreamingToolInputPreview(session._streamingToolInputPreviews, resultDelta.toolUseId);
20259
+ if (restPreviews) extraUpdates._streamingToolInputPreviews = restPreviews;
20260
+ const applied = applyTodoResult(session, resultDelta);
20261
+ if (applied) extraUpdates = { ...extraUpdates, ...applied };
20262
+ }
20078
20263
  return { messages: updatedMessages, lastEventAt: ports2.now(), ...extraUpdates };
20079
20264
  }
20080
20265
  var init_content = __esm({
@@ -20094,80 +20279,6 @@ var init_content = __esm({
20094
20279
  }
20095
20280
  });
20096
20281
 
20097
- // ../../packages/shared/src/transcript-boundary.ts
20098
- function contentKeys(content) {
20099
- const counts = /* @__PURE__ */ new Map();
20100
- return content.map((block) => {
20101
- if (isToolUseBlock(block)) return `tool:${block.toolUseId}`;
20102
- if (isToolResultBlock(block)) return `result:${block.toolUseId}`;
20103
- const parent = "parentToolUseId" in block ? block.parentToolUseId ?? "" : "";
20104
- const kind = `${block.type}:${parent}`;
20105
- const count = counts.get(kind) ?? 0;
20106
- counts.set(kind, count + 1);
20107
- return `${kind}:${count}`;
20108
- });
20109
- }
20110
- function blockText(block) {
20111
- return block.type === "text" ? block.text : block.type === "thinking" ? block.thinking : void 0;
20112
- }
20113
- function itemText(item) {
20114
- return "text" in item ? item.text : void 0;
20115
- }
20116
- function transcriptLengths(message) {
20117
- const keys = contentKeys(message.content);
20118
- return {
20119
- content: Object.fromEntries(message.content.map((block, index) => [keys[index], blockText(block)?.length ?? -1])),
20120
- items: Object.fromEntries((message.metadata?.codex?.items ?? []).map((item) => [item.id, itemText(item)?.length ?? -1]))
20121
- };
20122
- }
20123
- function resolveTranscriptBoundaries(cuts, lengths) {
20124
- let previous = { content: {}, items: {} };
20125
- return cuts.map((cut) => {
20126
- const cursor = cut.metadata.transcriptBoundary;
20127
- const asyncAnswer = isCodexAsyncAnswer(cut);
20128
- const resolved = { ...cursor, content: { ...previous.content }, items: { ...previous.items } };
20129
- for (const kind of ["content", "items"]) {
20130
- for (const [key, offset] of Object.entries(cursor[kind])) {
20131
- const end = asyncAnswer ? lengths[kind][key] ?? offset : offset;
20132
- resolved[kind][key] = Math.max(previous[kind][key] ?? -1, end);
20133
- }
20134
- }
20135
- previous = resolved;
20136
- return resolved;
20137
- });
20138
- }
20139
- function captureTranscriptBoundary(message, messages = []) {
20140
- let order = capturedOrders.get(message.id) ?? 0;
20141
- for (const row2 of messages) {
20142
- const cursor = row2.metadata?.transcriptBoundary;
20143
- if (cursor?.messageId === message.id) order = Math.max(order, cursor.order);
20144
- }
20145
- order += 1;
20146
- capturedOrders.delete(message.id);
20147
- capturedOrders.set(message.id, order);
20148
- if (capturedOrders.size > 1024) capturedOrders.delete(capturedOrders.keys().next().value);
20149
- return {
20150
- messageId: message.id,
20151
- order,
20152
- ...transcriptLengths(message)
20153
- };
20154
- }
20155
- function anchorAsyncAnswer(message, messages) {
20156
- if (!isCodexAsyncAnswer(message) || message.metadata?.transcriptBoundary) return message;
20157
- const itemId = message.id.slice("codex_async_answer:".length);
20158
- const source = messages.findLast((row2) => row2.status === "streaming" && row2.role === "assistant" && codexAsyncQuestionItems(row2).some((item) => item.id === itemId)) ?? messages.findLast((row2) => row2.status === "streaming" && row2.role === "assistant" && row2.providerId === "codex");
20159
- return source ? { ...message, metadata: { ...message.metadata, transcriptBoundary: captureTranscriptBoundary(source, messages) } } : message;
20160
- }
20161
- var capturedOrders;
20162
- var init_transcript_boundary = __esm({
20163
- "../../packages/shared/src/transcript-boundary.ts"() {
20164
- "use strict";
20165
- init_codex_async_question();
20166
- init_content_delta();
20167
- capturedOrders = /* @__PURE__ */ new Map();
20168
- }
20169
- });
20170
-
20171
20282
  // ../../packages/shared/src/codex-timeline-rows.ts
20172
20283
  function stampCodexTimelineOrder(message, event) {
20173
20284
  const timeline = message.metadata?.codexTimeline;
@@ -22326,7 +22437,8 @@ var init_read_model = __esm({
22326
22437
  idColumn: "message_id",
22327
22438
  columns: "message_json, sort_order",
22328
22439
  sessionId,
22329
- parse: (row2) => JSON.parse(row2.message_json)
22440
+ parse: (row2) => JSON.parse(row2.message_json),
22441
+ boundarySql: `SELECT message_json, sort_order FROM session_messages WHERE session_id = ? AND instr(message_json, '"transcriptBoundary"') > 0 ORDER BY sort_order ASC`
22330
22442
  }),
22331
22443
  state: includeState ? coreState(core) : {},
22332
22444
  cursor: { sequence: this.log.headSequence(), epoch: this.log.epoch, version: checkpoint.applied_version }
@@ -40500,6 +40612,7 @@ var UI_SURFACE_CAPABILITY, ModUiUnavailableError, ModSurface;
40500
40612
  var init_mod_surface = __esm({
40501
40613
  "../../packages/claude/src/mod-surface/mod-surface.ts"() {
40502
40614
  "use strict";
40615
+ init_slash_commands();
40503
40616
  init_mod_ui();
40504
40617
  init_wire();
40505
40618
  UI_SURFACE_CAPABILITY = "ui_surface_v1";
@@ -40520,7 +40633,10 @@ var init_mod_surface = __esm({
40520
40633
  promptSuggest: (req) => this.relayHostRequest("promptSuggest", req)
40521
40634
  });
40522
40635
  void query.initializationResult?.().then(
40523
- (init) => this.setAvailable(Array.isArray(init?.capabilities) && init.capabilities.includes(UI_SURFACE_CAPABILITY)),
40636
+ (init) => {
40637
+ this.setAvailable(Array.isArray(init?.capabilities) && init.capabilities.includes(UI_SURFACE_CAPABILITY));
40638
+ if (!this.disposed && Array.isArray(init?.commands)) this.opts.emit({ type: "session_commands", commands: sdkSlashCommands(init.commands, void 0) });
40639
+ },
40524
40640
  () => this.setAvailable(false)
40525
40641
  );
40526
40642
  }
@@ -42556,21 +42672,21 @@ function extractThinkingFromAssistant(item) {
42556
42672
  return asString4(get(item, "reasoning_content"));
42557
42673
  }
42558
42674
  function claudeToolUseToChatToolCall(item) {
42559
- const callId = asString4(get(item, "id")) ?? asString4(get(item, "tool_use_id"));
42675
+ const callId2 = asString4(get(item, "id")) ?? asString4(get(item, "tool_use_id"));
42560
42676
  const name = asString4(get(item, "name"));
42561
- if (!callId || !name) return void 0;
42677
+ if (!callId2 || !name) return void 0;
42562
42678
  const input = get(item, "input") ?? get(item, "arguments");
42563
42679
  return {
42564
- id: callId,
42680
+ id: callId2,
42565
42681
  type: "function",
42566
42682
  function: { name, arguments: canonicalizeToolArguments(input) }
42567
42683
  };
42568
42684
  }
42569
42685
  function claudeFunctionCallToChatToolCall(functionCall) {
42570
- const callId = asString4(get(functionCall, "id")) ?? "call_0";
42686
+ const callId2 = asString4(get(functionCall, "id")) ?? "call_0";
42571
42687
  const name = asString4(get(functionCall, "name")) ?? "";
42572
42688
  const args = canonicalizeToolArguments(get(functionCall, "arguments"));
42573
- return { id: callId, type: "function", function: { name, arguments: args } };
42689
+ return { id: callId2, type: "function", function: { name, arguments: args } };
42574
42690
  }
42575
42691
  function claudeToolResultToChat(item) {
42576
42692
  const toolUseId = asString4(get(item, "tool_use_id")) ?? asString4(get(item, "call_id")) ?? "";
@@ -42761,24 +42877,24 @@ function chatToolCallsToOutputItems(message) {
42761
42877
  return output;
42762
42878
  }
42763
42879
  function chatToolCallToOutputItem(toolCall, index) {
42764
- const callId = asString4(get(toolCall, "id"))?.trim() || `call_${index}`;
42880
+ const callId2 = asString4(get(toolCall, "id"))?.trim() || `call_${index}`;
42765
42881
  const fn = get(toolCall, "function");
42766
42882
  const name = asString4(get(fn, "name")) ?? "";
42767
42883
  const args = canonicalizeToolArguments(get(fn, "arguments"));
42768
42884
  return {
42769
42885
  type: "tool_use",
42770
- id: callId,
42886
+ id: callId2,
42771
42887
  name,
42772
42888
  input: safeJsonParse(args)
42773
42889
  };
42774
42890
  }
42775
42891
  function chatLegacyFunctionCallToOutputItem(functionCall) {
42776
- const callId = asString4(get(functionCall, "id"))?.trim() || "call_0";
42892
+ const callId2 = asString4(get(functionCall, "id"))?.trim() || "call_0";
42777
42893
  const name = asString4(get(functionCall, "name")) ?? "";
42778
42894
  const args = canonicalizeToolArguments(get(functionCall, "arguments"));
42779
42895
  return {
42780
42896
  type: "tool_use",
42781
- id: callId,
42897
+ id: callId2,
42782
42898
  name,
42783
42899
  input: safeJsonParse(args)
42784
42900
  };
@@ -43766,8 +43882,8 @@ function appendResponsesItem(item, messages, state) {
43766
43882
  }
43767
43883
  case "function_call_output": {
43768
43884
  flushPendingToolCalls(messages, state);
43769
- const callId = asString6(get2(item, "call_id")) ?? "";
43770
- messages.push({ role: "tool", tool_call_id: callId, content: functionCallOutput(get2(item, "output")) });
43885
+ const callId2 = asString6(get2(item, "call_id")) ?? "";
43886
+ messages.push({ role: "tool", tool_call_id: callId2, content: functionCallOutput(get2(item, "output")) });
43771
43887
  return;
43772
43888
  }
43773
43889
  case "reasoning": {
@@ -43899,10 +44015,10 @@ function responsesContentToChatContent(content) {
43899
44015
  return chatParts;
43900
44016
  }
43901
44017
  function responsesFunctionCallToChatToolCall(item) {
43902
- const callId = asString6(get2(item, "call_id")) ?? asString6(get2(item, "id")) ?? "";
44018
+ const callId2 = asString6(get2(item, "call_id")) ?? asString6(get2(item, "id")) ?? "";
43903
44019
  const name = asString6(get2(item, "name")) ?? "";
43904
44020
  return {
43905
- id: callId,
44021
+ id: callId2,
43906
44022
  type: "function",
43907
44023
  function: { name, arguments: canonicalizeToolArguments2(get2(item, "arguments")) }
43908
44024
  };
@@ -44069,12 +44185,12 @@ function chatToolCallsToOutputItems2(message, reasoning) {
44069
44185
  }
44070
44186
  return output;
44071
44187
  }
44072
- function functionCallItem(itemId, callId, name, args, reasoning) {
44188
+ function functionCallItem(itemId, callId2, name, args, reasoning) {
44073
44189
  const item = {
44074
44190
  id: itemId,
44075
44191
  type: "function_call",
44076
44192
  status: "completed",
44077
- call_id: callId,
44193
+ call_id: callId2,
44078
44194
  name,
44079
44195
  arguments: args
44080
44196
  };
@@ -44082,17 +44198,17 @@ function functionCallItem(itemId, callId, name, args, reasoning) {
44082
44198
  return item;
44083
44199
  }
44084
44200
  function chatToolCallToOutputItem2(toolCall, index, reasoning) {
44085
- const callId = asString6(get2(toolCall, "id"))?.trim() || `call_${index}`;
44201
+ const callId2 = asString6(get2(toolCall, "id"))?.trim() || `call_${index}`;
44086
44202
  const fn = get2(toolCall, "function");
44087
44203
  const name = asString6(get2(fn, "name")) ?? "";
44088
44204
  const args = canonicalizeToolArguments2(get2(fn, "arguments"));
44089
- return functionCallItem(`fc_${callId}`, callId, name, args, reasoning);
44205
+ return functionCallItem(`fc_${callId2}`, callId2, name, args, reasoning);
44090
44206
  }
44091
44207
  function chatLegacyFunctionCallToOutputItem2(functionCall, reasoning) {
44092
- const callId = asString6(get2(functionCall, "id"))?.trim() || "call_0";
44208
+ const callId2 = asString6(get2(functionCall, "id"))?.trim() || "call_0";
44093
44209
  const name = asString6(get2(functionCall, "name")) ?? "";
44094
44210
  const args = canonicalizeToolArguments2(get2(functionCall, "arguments"));
44095
- return functionCallItem(`fc_${callId}`, callId, name, args, reasoning);
44211
+ return functionCallItem(`fc_${callId2}`, callId2, name, args, reasoning);
44096
44212
  }
44097
44213
  function chatUsageToResponsesUsage(usage2) {
44098
44214
  const obj = asObject4(usage2);
@@ -44164,12 +44280,12 @@ data: ${JSON.stringify(data)}
44164
44280
 
44165
44281
  `;
44166
44282
  }
44167
- function functionCallItem2(itemId, status2, callId, name, args, reasoning) {
44283
+ function functionCallItem2(itemId, status2, callId2, name, args, reasoning) {
44168
44284
  const item = {
44169
44285
  id: itemId,
44170
44286
  type: "function_call",
44171
44287
  status: status2,
44172
- call_id: callId,
44288
+ call_id: callId2,
44173
44289
  name,
44174
44290
  arguments: args
44175
44291
  };
@@ -70763,23 +70879,6 @@ var init_computer_use_result_shape = __esm({
70763
70879
  }
70764
70880
  });
70765
70881
 
70766
- // ../../packages/shared/src/jev-run-result-shape.ts
70767
- function isJevRunToolName(toolName) {
70768
- if (!toolName) return false;
70769
- return /(?:^|__)(?:browser|computer|device)_run$/.test(toolName);
70770
- }
70771
- function looksLikeJevRunResult(obj) {
70772
- const status2 = obj.status;
70773
- if (status2 !== "paused" && status2 !== "done" && status2 !== "aborted") return false;
70774
- if (typeof obj.runId !== "string") return false;
70775
- return Array.isArray(obj.since_last) || typeof obj.progress === "object" && obj.progress !== null || typeof obj.steps === "number";
70776
- }
70777
- var init_jev_run_result_shape = __esm({
70778
- "../../packages/shared/src/jev-run-result-shape.ts"() {
70779
- "use strict";
70780
- }
70781
- });
70782
-
70783
70882
  // ../../packages/acp/src/tool-result-map.ts
70784
70883
  function formatAcpRawOutput(raw) {
70785
70884
  return formatAgentToolOutput(raw);
@@ -73042,13 +73141,13 @@ function createAcpAgentTurnRunner(opts = {}) {
73042
73141
  if (!input.onPlan) return formatGrokExitPlanCancelled();
73043
73142
  const raw = ctx.params && typeof ctx.params === "object" && !Array.isArray(ctx.params) ? ctx.params : {};
73044
73143
  const toolCallId = typeof raw.toolCallId === "string" ? raw.toolCallId : typeof raw.tool_call_id === "string" ? raw.tool_call_id : `acp_plan_${Date.now().toString(36)}`;
73045
- const planContent = typeof raw.planContent === "string" ? raw.planContent : typeof raw.plan_content === "string" ? raw.plan_content : "";
73144
+ const planContent2 = typeof raw.planContent === "string" ? raw.planContent : typeof raw.plan_content === "string" ? raw.plan_content : "";
73046
73145
  try {
73047
73146
  const result3 = await input.onPlan({
73048
73147
  interactionId: toolCallId,
73049
73148
  kind: "plan",
73050
73149
  toolUseId: toolCallId,
73051
- input: { planContent, ...raw },
73150
+ input: { planContent: planContent2, ...raw },
73052
73151
  createdAt: Date.now()
73053
73152
  });
73054
73153
  return formatGrokExitPlanFromDecision(result3.decision, result3.options);
@@ -73415,7 +73514,7 @@ async function waitForServer(child, exited, timeoutMs, signal2) {
73415
73514
  let output = "";
73416
73515
  return new Promise((resolve22, reject) => {
73417
73516
  let settled = false;
73418
- const finish = (error51, url2) => {
73517
+ const finish2 = (error51, url2) => {
73419
73518
  if (settled) return;
73420
73519
  settled = true;
73421
73520
  clearTimeout(timer);
@@ -73428,18 +73527,18 @@ async function waitForServer(child, exited, timeoutMs, signal2) {
73428
73527
  const onData = (chunk) => {
73429
73528
  output = appendOutput(output, chunk);
73430
73529
  const match = output.match(/^(?:opencode )?server listening.*?\s+(https?:\/\/[^\s]+)/im);
73431
- if (match?.[1]) finish(void 0, match[1]);
73530
+ if (match?.[1]) finish2(void 0, match[1]);
73432
73531
  };
73433
- const onAbort = () => finish(new Error("OpenCode server startup aborted"));
73532
+ const onAbort = () => finish2(new Error("OpenCode server startup aborted"));
73434
73533
  const timer = setTimeout(
73435
- () => finish(new Error(`Timed out waiting for OpenCode server: ${output.trim()}`)),
73534
+ () => finish2(new Error(`Timed out waiting for OpenCode server: ${output.trim()}`)),
73436
73535
  timeoutMs
73437
73536
  );
73438
73537
  child.stdout.on("data", onData);
73439
73538
  child.stderr.on("data", onData);
73440
- child.once("error", (error51) => finish(error51));
73539
+ child.once("error", (error51) => finish2(error51));
73441
73540
  void exited.then(
73442
- ({ code, signal: sig }) => finish(new Error(`OpenCode server exited (${code ?? sig ?? "unknown"}): ${output.trim()}`))
73541
+ ({ code, signal: sig }) => finish2(new Error(`OpenCode server exited (${code ?? sig ?? "unknown"}): ${output.trim()}`))
73443
73542
  );
73444
73543
  signal2?.addEventListener("abort", onAbort, { once: true });
73445
73544
  if (signal2?.aborted) onAbort();
@@ -73466,13 +73565,13 @@ async function startOpenCodeServer(opts) {
73466
73565
  });
73467
73566
  const exited = new Promise((resolve22) => {
73468
73567
  let settled = false;
73469
- const finish = (code, signal2) => {
73568
+ const finish2 = (code, signal2) => {
73470
73569
  if (settled) return;
73471
73570
  settled = true;
73472
73571
  resolve22({ code, signal: signal2 });
73473
73572
  };
73474
- child.once("exit", finish);
73475
- child.once("close", finish);
73573
+ child.once("exit", finish2);
73574
+ child.once("close", finish2);
73476
73575
  });
73477
73576
  try {
73478
73577
  const url2 = await waitForServer(child, exited, opts.timeoutMs ?? 1e4, opts.signal);
@@ -74429,7 +74528,7 @@ var init_client_gen2 = __esm({
74429
74528
  });
74430
74529
 
74431
74530
  // ../../node_modules/@opencode-ai/sdk/dist/v2/gen/sdk.gen.js
74432
- var HeyApiClient, HeyApiRegistry, Auth, App, ControlPlane, Capabilities, Console, Session, Resource, ProjectCopy, Adapter, Workspace, Experimental, Config, Global, Event2, Config2, Tool, Worktree, Find, File2, Instance, Path, Diff2, Vcs, Command, Lsp, Formatter, Auth2, Mcp, Project, Pty, Question, Permission, Oauth, Provider, Session2, Part, History, Sync, Control, Tui, Health, Location, Agent, Revert, Permission2, Question2, Session3, Model, Provider2, Connect, Attempt, Integration, Credential, Request2, Saved, Permission3, Fs2, Command2, Skill, Event22, Pty2, Request22, Question3, Reference, ProjectCopy2, V2, OpencodeClient;
74531
+ var HeyApiClient, HeyApiRegistry, Auth, App, ControlPlane, Capabilities, Console, Session, Resource, ProjectCopy, Adapter, Workspace, Experimental, Config, Global, Event2, Config2, Tool, Worktree, Find, File2, Instance, Path, Diff3, Vcs, Command, Lsp, Formatter, Auth2, Mcp, Project, Pty, Question, Permission, Oauth, Provider, Session2, Part, History, Sync, Control, Tui, Health, Location, Agent, Revert, Permission2, Question2, Session3, Model, Provider2, Connect, Attempt, Integration, Credential, Request2, Saved, Permission3, Fs2, Command2, Skill, Event22, Pty2, Request22, Question3, Reference, ProjectCopy2, V2, OpencodeClient;
74433
74532
  var init_sdk_gen = __esm({
74434
74533
  "../../node_modules/@opencode-ai/sdk/dist/v2/gen/sdk.gen.js"() {
74435
74534
  init_client_gen2();
@@ -75478,7 +75577,7 @@ var init_sdk_gen = __esm({
75478
75577
  });
75479
75578
  }
75480
75579
  };
75481
- Diff2 = class extends HeyApiClient {
75580
+ Diff3 = class extends HeyApiClient {
75482
75581
  /**
75483
75582
  * Get raw VCS diff
75484
75583
  *
@@ -75591,7 +75690,7 @@ var init_sdk_gen = __esm({
75591
75690
  }
75592
75691
  _diff;
75593
75692
  get diff2() {
75594
- return this._diff ??= new Diff2({ client: this.client });
75693
+ return this._diff ??= new Diff3({ client: this.client });
75595
75694
  }
75596
75695
  };
75597
75696
  Command = class extends HeyApiClient {
@@ -80160,7 +80259,7 @@ function make7(connect) {
80160
80259
  let started = false;
80161
80260
  let completion;
80162
80261
  let connection;
80163
- function finish(result3, discard = true) {
80262
+ function finish2(result3, discard = true) {
80164
80263
  completion = result3;
80165
80264
  if (discard)
80166
80265
  queued.length = 0;
@@ -80175,12 +80274,12 @@ function make7(connect) {
80175
80274
  });
80176
80275
  }
80177
80276
  function abort() {
80178
- finish({});
80277
+ finish2({});
80179
80278
  }
80180
80279
  const subscriber = {
80181
80280
  activity: options?.onActivity,
80182
80281
  finish(result3) {
80183
- finish(result3, false);
80282
+ finish2(result3, false);
80184
80283
  },
80185
80284
  push(value) {
80186
80285
  if (completion)
@@ -80191,7 +80290,7 @@ function make7(connect) {
80191
80290
  return;
80192
80291
  }
80193
80292
  if (queued.length === capacity) {
80194
- finish({ error: new Error(`Event subscriber exceeded its ${capacity}-event capacity`) });
80293
+ finish2({ error: new Error(`Event subscriber exceeded its ${capacity}-event capacity`) });
80195
80294
  return;
80196
80295
  }
80197
80296
  queued.push(value);
@@ -80236,7 +80335,7 @@ function make7(connect) {
80236
80335
  return request.promise;
80237
80336
  },
80238
80337
  return() {
80239
- finish({});
80338
+ finish2({});
80240
80339
  return Promise.resolve({ done: true, value: void 0 });
80241
80340
  }
80242
80341
  };
@@ -82514,18 +82613,18 @@ var init_opencode_v2_event_map = __esm({
82514
82613
  switch (event.type) {
82515
82614
  case "permission.asked": {
82516
82615
  const data = event.data;
82517
- const callId = data.source?.id;
82616
+ const callId2 = data.source?.id;
82518
82617
  return [{
82519
82618
  type: "permission",
82520
82619
  permission: data.action,
82521
- toolInput: callId && this.toolInputs.get(callId) || null,
82620
+ toolInput: callId2 && this.toolInputs.get(callId2) || null,
82522
82621
  request: mapOpenCodePermissionRequest({
82523
82622
  id: data.id,
82524
82623
  permission: data.action,
82525
82624
  patterns: data.resources,
82526
82625
  metadata: data.metadata,
82527
82626
  always: data.save,
82528
- toolUseId: callId,
82627
+ toolUseId: callId2,
82529
82628
  message: data.message,
82530
82629
  source: data.source ? {
82531
82630
  toolUseId: data.source.id,
@@ -83598,18 +83697,18 @@ var init_opencode_oauth = __esm({
83598
83697
  throw new Error("This OpenCode sign-in method requires an unsupported external form field");
83599
83698
  const form = { id: `superone-oauth-${randomUUID13()}`, sessionID: this.deps.sessionId, title: title2, fields };
83600
83699
  return new Promise((resolve22, reject) => {
83601
- const finish = (answer) => {
83700
+ const finish2 = (answer) => {
83602
83701
  this.forms.delete(form.id);
83603
83702
  signal2.removeEventListener("abort", aborted2);
83604
83703
  this.emit(answer ? "form.replied" : "form.cancelled", { id: form.id, ...answer ? { answer } : {} });
83605
83704
  if (answer) resolve22(answer);
83606
83705
  else reject(signal2.reason ?? new Error("OpenCode sign-in cancelled"));
83607
83706
  };
83608
- const aborted2 = () => finish();
83707
+ const aborted2 = () => finish2();
83609
83708
  this.forms.set(form.id, {
83610
83709
  form,
83611
83710
  owner: controller,
83612
- reply: (answer) => finish(answer),
83711
+ reply: (answer) => finish2(answer),
83613
83712
  cancel: () => controller.abort(new Error("OpenCode sign-in cancelled"))
83614
83713
  });
83615
83714
  signal2.addEventListener("abort", aborted2, { once: true });
@@ -83982,17 +84081,17 @@ async function createOpenCodeV2Runtime(server, opts, ports2) {
83982
84081
  if (agentRevision !== revision) return Promise.resolve();
83983
84082
  abortController.signal.throwIfAborted();
83984
84083
  return new Promise((resolve22, reject) => {
83985
- const finish = (error51) => {
84084
+ const finish2 = (error51) => {
83986
84085
  clearTimeout(timer);
83987
84086
  agentCatalogWaiters.delete(updated);
83988
84087
  abortController.signal.removeEventListener("abort", aborted2);
83989
84088
  if (error51) reject(error51);
83990
84089
  else resolve22();
83991
84090
  };
83992
- const updated = () => finish();
83993
- const aborted2 = () => finish(abortController.signal.reason);
84091
+ const updated = () => finish2();
84092
+ const aborted2 = () => finish2(abortController.signal.reason);
83994
84093
  const timer = setTimeout(
83995
- () => finish(new Error("OpenCode agent catalog did not finish loading; try refreshing again")),
84094
+ () => finish2(new Error("OpenCode agent catalog did not finish loading; try refreshing again")),
83996
84095
  3e3
83997
84096
  );
83998
84097
  agentCatalogWaiters.add(updated);
@@ -86875,7 +86974,7 @@ function stringifyPayload(value) {
86875
86974
  }
86876
86975
  function extractToolCallParts(update) {
86877
86976
  const rec = asRecord17(update) ?? {};
86878
- const callId = extractCursorCallId(update);
86977
+ const callId2 = extractCursorCallId(update);
86879
86978
  const nested = asRecord17(rec.toolCall);
86880
86979
  if (nested) {
86881
86980
  const toolType2 = typeof nested.type === "string" && nested.type ? nested.type : "Tool";
@@ -86883,7 +86982,7 @@ function extractToolCallParts(update) {
86883
86982
  const resultRec = asRecord17(result3);
86884
86983
  const isError = resultRec?.status === "error" || Boolean(rec.isError);
86885
86984
  return {
86886
- callId,
86985
+ callId: callId2,
86887
86986
  toolType: toolType2,
86888
86987
  args: nested.args ?? nested.input ?? {},
86889
86988
  result: resultRec?.status === "success" ? resultRec.value ?? result3 : resultRec?.status === "error" ? resultRec.error ?? result3 : result3,
@@ -86892,7 +86991,7 @@ function extractToolCallParts(update) {
86892
86991
  }
86893
86992
  const toolType = strField2(rec, "name") || strField2(rec, "type") || "Tool";
86894
86993
  return {
86895
- callId,
86994
+ callId: callId2,
86896
86995
  toolType,
86897
86996
  args: rec.args ?? rec.input ?? {},
86898
86997
  result: rec.result,
@@ -86927,7 +87026,7 @@ function canonicalizeCursorHostTool(toolType, args, result3) {
86927
87026
  ...shaped.isError ? { resultIsError: true } : {}
86928
87027
  };
86929
87028
  }
86930
- function toolUseEvent(messageId, callId, toolType, args, status2, result3) {
87029
+ function toolUseEvent(messageId, callId2, toolType, args, status2, result3) {
86931
87030
  const mcp = unwrapCursorMcpTool(toolType, args);
86932
87031
  const unwrapped = canonicalizeCursorHostTool(mcp.toolType, mcp.args, result3);
86933
87032
  const toolName = toolDisplayName(unwrapped.toolType);
@@ -86937,7 +87036,7 @@ function toolUseEvent(messageId, callId, toolType, args, status2, result3) {
86937
87036
  delta: {
86938
87037
  type: "tool_use",
86939
87038
  toolName,
86940
- toolUseId: callId,
87039
+ toolUseId: callId2,
86941
87040
  input: stringifyPayload(normalizeCursorToolInput(toolName, unwrapped.args)),
86942
87041
  status: status2,
86943
87042
  ...status2 === "streaming" ? { startedAt: Date.now() } : {}
@@ -86976,14 +87075,14 @@ function mergeCursorToolResultArgs(toolType, args, result3) {
86976
87075
  }
86977
87076
  return changed ? next : rec;
86978
87077
  }
86979
- function toolResultEvent(messageId, callId, result3, isError, toolType, args) {
87078
+ function toolResultEvent(messageId, callId2, result3, isError, toolType, args) {
86980
87079
  const host = toolType != null ? canonicalizeCursorHostTool(unwrapCursorMcpTool(toolType, args).toolType, args, result3) : null;
86981
87080
  return {
86982
87081
  type: "content_delta",
86983
87082
  messageId,
86984
87083
  delta: {
86985
87084
  type: "tool_result",
86986
- toolUseId: callId,
87085
+ toolUseId: callId2,
86987
87086
  summary: host?.resultSummary ?? (formatTranscriptToolResult(result3) || stringifyPayload(result3)),
86988
87087
  isError: isError || host?.resultIsError === true
86989
87088
  }
@@ -87206,8 +87305,8 @@ function mapConversationStep(messageId, step, options) {
87206
87305
  if (stepType === "toolCall") {
87207
87306
  const message = rec.message ?? rec.toolCall ?? rec;
87208
87307
  const nested = asRecord17(message);
87209
- const callId = extractCursorCallId(rec) || options?.resolveCallId?.(step) || null;
87210
- if (!callId) {
87308
+ const callId2 = extractCursorCallId(rec) || options?.resolveCallId?.(step) || null;
87309
+ if (!callId2) {
87211
87310
  return events;
87212
87311
  }
87213
87312
  const toolType = nested && typeof nested.type === "string" && nested.type ? nested.type : strField2(rec, "name") || "Tool";
@@ -87216,7 +87315,7 @@ function mapConversationStep(messageId, step, options) {
87216
87315
  const resultValue = resultRec?.status === "success" ? resultRec.value ?? nested?.result : nested?.result;
87217
87316
  events.push(toolUseEvent(
87218
87317
  messageId,
87219
- callId,
87318
+ callId2,
87220
87319
  toolType,
87221
87320
  mergeCursorToolResultArgs(toolType, args, resultValue),
87222
87321
  "complete"
@@ -87491,10 +87590,10 @@ var init_cursor_event_map = __esm({
87491
87590
  if (type !== "tool-call-started" && type !== "partial-tool-call" && type !== "tool-call-completed") {
87492
87591
  return;
87493
87592
  }
87494
- const callId = extractCursorCallId(update);
87495
- if (!callId || this.seen.has(callId)) return;
87496
- this.seen.add(callId);
87497
- this.queue.push(callId);
87593
+ const callId2 = extractCursorCallId(update);
87594
+ if (!callId2 || this.seen.has(callId2)) return;
87595
+ this.seen.add(callId2);
87596
+ this.queue.push(callId2);
87498
87597
  }
87499
87598
  /** FIFO claim for the next onStep toolCall (or null if nothing to associate). */
87500
87599
  claimNextCallId() {
@@ -100520,6 +100619,44 @@ function resolveTodoToolTodos(toolName, input, resultToolTodos) {
100520
100619
  if (computed?.length) return [{ ...computed[0], taskId: resolvedId }];
100521
100620
  return resultToolTodos;
100522
100621
  }
100622
+ function todoItemsForResult(toolName, input, resultToolTodos) {
100623
+ const items = resolveTodoToolTodos(toolName, input, resultToolTodos);
100624
+ if (toolName !== "TaskUpdate" || !items?.[0]) return items;
100625
+ let status2;
100626
+ try {
100627
+ status2 = JSON.parse(input)?.status;
100628
+ } catch {
100629
+ return items;
100630
+ }
100631
+ if (status2 == null || status2 === "") return [{ ...items[0], status: "" }];
100632
+ return items;
100633
+ }
100634
+ function todoResultForCall(toolName, input, result3) {
100635
+ const toolTodos = result3.isError ? void 0 : todoItemsForResult(toolName, input, result3.toolTodos);
100636
+ return {
100637
+ type: "todo_result",
100638
+ toolUseId: result3.toolUseId,
100639
+ summary: result3.summary,
100640
+ parentToolUseId: result3.parentToolUseId,
100641
+ todoToolName: toolName,
100642
+ ...toolTodos ? { toolTodos } : {}
100643
+ };
100644
+ }
100645
+ function revealTodoResults(message) {
100646
+ const calls2 = /* @__PURE__ */ new Map();
100647
+ for (const block of message.content) {
100648
+ if (block.type === "tool_use" && TODO_TOOLS.has(block.toolName)) calls2.set(block.toolUseId, { toolName: block.toolName, input: block.input });
100649
+ }
100650
+ if (!calls2.size) return message;
100651
+ let changed = false;
100652
+ const content = message.content.map((block) => {
100653
+ if (block.type !== "tool_result" || !calls2.has(block.toolUseId)) return block;
100654
+ const entry3 = calls2.get(block.toolUseId);
100655
+ changed = true;
100656
+ return todoResultForCall(entry3.toolName, entry3.input, block);
100657
+ });
100658
+ return changed ? { ...message, content } : message;
100659
+ }
100523
100660
  function countLines(s4) {
100524
100661
  if (!s4) return 0;
100525
100662
  return s4.split("\n").length;
@@ -100984,8 +101121,7 @@ function stripMessagesForRemote(messages, projectPath, options = {}) {
100984
101121
  content: msg.content.filter((b3) => !(b3.type === "tool_use" && TODO_TOOLS.has(b3.toolName))).flatMap((b3) => {
100985
101122
  if (b3.type === "tool_result" && todoInputs.has(b3.toolUseId)) {
100986
101123
  const entry3 = todoInputs.get(b3.toolUseId);
100987
- const toolTodos = resolveTodoToolTodos(entry3.toolName, entry3.input, b3.toolTodos);
100988
- return { type: "todo_result", toolUseId: b3.toolUseId, summary: b3.summary, parentToolUseId: b3.parentToolUseId, todoToolName: entry3.toolName, toolTodos };
101124
+ return todoResultForCall(entry3.toolName, entry3.input, b3);
100989
101125
  }
100990
101126
  if (b3.type === "tool_result" && widgetIds.has(b3.toolUseId)) return b3;
100991
101127
  if (b3.type === "text") {
@@ -101126,8 +101262,7 @@ var EventProfile = class {
101126
101262
  }
101127
101263
  if (event.delta.type === "tool_result" && tools.todoInputs.has(event.delta.toolUseId)) {
101128
101264
  const entry3 = tools.todoInputs.get(event.delta.toolUseId);
101129
- const toolTodos = resolveTodoToolTodos(entry3.toolName, entry3.input, event.delta.toolTodos);
101130
- return { ...event, delta: { type: "todo_result", toolUseId: event.delta.toolUseId, summary: event.delta.summary, parentToolUseId: event.delta.parentToolUseId, todoToolName: entry3.toolName, toolTodos } };
101265
+ return { ...event, delta: todoResultForCall(entry3.toolName, entry3.input, event.delta) };
101131
101266
  }
101132
101267
  if (event.delta.type === "tool_result" && tools.widgetIds.has(event.delta.toolUseId)) {
101133
101268
  return { ...event, delta: event.delta };
@@ -101428,6 +101563,15 @@ function toolDetail(message, id) {
101428
101563
  const result3 = message.content.find((block) => block.type === "tool_result" && block.toolUseId === id);
101429
101564
  const projected = stripMessagesForRemote([{ ...message, metadata: void 0, content: [tool2, ...result3 ? [result3] : []] }])[0].content[0];
101430
101565
  const children = message.content.filter((block) => block.type !== "thinking" && "parentToolUseId" in block && block.parentToolUseId === id).map((block) => "toolName" in block ? projectTool(block, JSON.stringify([message.id, "tool", block.toolUseId])) : block.type === "tool_result" ? { type: "tool_result", toolUseId: block.toolUseId, summary: "", isError: block.isError } : block);
101566
+ const transcriptChildren = children.some((block) => block.type === "tool_use") || !isSubagentToolName(tool2.toolName) || !tool2.taskOutputFile ? [] : remoteContentPorts().readAgentOutput(tool2.taskOutputFile).toolEntries.flatMap((entry3, index) => isAlwaysHiddenToolName(entry3.toolName) ? [] : [{
101567
+ type: "tool_use",
101568
+ toolName: entry3.toolName,
101569
+ toolUseId: `${id}:transcript:${index}`,
101570
+ input: "{}",
101571
+ status: "complete",
101572
+ toolSummary: entry3.description,
101573
+ parentToolUseId: id
101574
+ }]);
101431
101575
  const output = result3 && "summary" in result3 ? result3.summary : tool2.liveOutput;
101432
101576
  const projectedTool = projected && "toolName" in projected ? projected : void 0;
101433
101577
  const input = parseInput(tool2.input) ?? {};
@@ -101440,7 +101584,7 @@ function toolDetail(message, id) {
101440
101584
  // A background task's `result` is only its launch receipt; the run's own
101441
101585
  // output is patched onto the block when the task_notification lands.
101442
101586
  taskResultText: tool2.taskResultText,
101443
- childBlocks: children,
101587
+ childBlocks: transcriptChildren.length > 0 ? transcriptChildren : children,
101444
101588
  toolDiff: projectedTool?.toolDiff,
101445
101589
  toolDiffTokens: projectedTool?.toolDiffTokens,
101446
101590
  toolLineDelta: projectedTool?.toolLineDelta,
@@ -101716,7 +101860,9 @@ function projectEvent(event, messages) {
101716
101860
  return { ...event, delta: projectTool(event.delta, reference(event.messageId, "tool", event.delta.toolUseId)) };
101717
101861
  }
101718
101862
  if (event.type === "content_delta" && event.delta.type === "tool_result" && message) {
101719
- const projected = projectProgressiveMessage(message).content.find((block) => block.type === "tool_result" && block.toolUseId === event.delta.toolUseId);
101863
+ const toolUseId = event.delta.toolUseId;
101864
+ const revealed = revealTodoResults(message);
101865
+ const projected = projectProgressiveMessage(revealed).content.find((block) => (block.type === "tool_result" || block.type === "todo_result") && block.toolUseId === toolUseId);
101720
101866
  if (projected) return { ...event, delta: projected };
101721
101867
  }
101722
101868
  if ("metadata" in event && event.metadata?.codex) {
@@ -101726,6 +101872,9 @@ function projectEvent(event, messages) {
101726
101872
  return event;
101727
101873
  }
101728
101874
 
101875
+ // ../../packages/runtime/src/stream/delivery/window-views.ts
101876
+ init_codex_content();
101877
+
101729
101878
  // ../../packages/shared/src/transcript-window/content-digest.ts
101730
101879
  function contentDigest(input) {
101731
101880
  let a = 2166136261;
@@ -101856,17 +102005,19 @@ var MessageFragmenter = class {
101856
102005
  const previous = this.memo.get(message.id);
101857
102006
  const next = /* @__PURE__ */ new Map();
101858
102007
  const fragments = (message.attachments ?? []).map((attachment, index) => attachmentEntry(index, attachment));
102008
+ const blocks = fragments.map(() => -1);
101859
102009
  const keys = blockKeys(content);
101860
102010
  content.forEach((block, index) => {
101861
102011
  const key = keys[index];
101862
102012
  const memo = blockFragments(block, key, previous?.get(key));
101863
102013
  next.set(key, memo);
101864
102014
  fragments.push(...memo.entries);
102015
+ for (let i = 0; i < memo.entries.length; i++) blocks.push(index);
101865
102016
  });
101866
102017
  this.memo.set(message.id, next);
101867
102018
  const meta3 = windowMeta(message);
101868
102019
  const metaJson = JSON.stringify(meta3);
101869
- return { id: message.id, meta: meta3, metaDigest: contentDigest(metaJson), metaBytes: utf8Length(metaJson), fragments };
102020
+ return { id: message.id, meta: meta3, metaDigest: contentDigest(metaJson), metaBytes: utf8Length(metaJson), fragments, blocks };
101870
102021
  }
101871
102022
  forget(messageId) {
101872
102023
  this.memo.delete(messageId);
@@ -101970,6 +102121,77 @@ function fitMeta(meta3) {
101970
102121
  return bare;
101971
102122
  }
101972
102123
 
102124
+ // ../../packages/shared/src/transcript-window/folds.ts
102125
+ var FOLD_KEY_PREFIX = "fold:";
102126
+ var PAGE_BLOCK_CHARS = 120;
102127
+ function foldRevision(fragments) {
102128
+ return contentDigest(fragments.map((fragment) => `${fragment.key} ${fragment.digest}`).join("\n"));
102129
+ }
102130
+ function foldMessageFragments(message, ranges) {
102131
+ const fragments = [];
102132
+ const blocks = [];
102133
+ const folds = /* @__PURE__ */ new Map();
102134
+ let r = 0;
102135
+ for (let i = 0; i < message.fragments.length; ) {
102136
+ const block = message.blocks[i];
102137
+ while (r < ranges.length && ranges[r].end < block) r++;
102138
+ const range = ranges[r];
102139
+ if (!range || block < range.start) {
102140
+ fragments.push(message.fragments[i]);
102141
+ blocks.push(block);
102142
+ i++;
102143
+ continue;
102144
+ }
102145
+ const inner = { entries: [], blocks: [] };
102146
+ for (; i < message.fragments.length && message.blocks[i] <= range.end; i++) {
102147
+ inner.entries.push(message.fragments[i]);
102148
+ inner.blocks.push(message.blocks[i]);
102149
+ }
102150
+ const key = FOLD_KEY_PREFIX + inner.entries[0].key;
102151
+ folds.set(key, inner);
102152
+ fragments.push(entry(key, { kind: "fold", revision: foldRevision(inner.entries), summary: { ...range.summary, fragments: inner.entries.length } }, 0));
102153
+ blocks.push(range.start);
102154
+ r++;
102155
+ }
102156
+ return { ...message, fragments, blocks, folds };
102157
+ }
102158
+ function selectFoldPage(inner, after, budget) {
102159
+ const start = after === void 0 ? 0 : inner.entries.findIndex((fragment) => fragment.key === after) + 1;
102160
+ if (start <= 0 && after !== void 0) return null;
102161
+ let end = start;
102162
+ let bytes = 0;
102163
+ let chars = 0;
102164
+ const calls2 = /* @__PURE__ */ new Set();
102165
+ for (; end < inner.entries.length; end++) {
102166
+ const fragment = inner.entries[end];
102167
+ if (end > start && (end - start >= budget.maxFragments || bytes + fragment.bytes > budget.maxBytes || chars >= budget.targetChars)) break;
102168
+ bytes += fragment.bytes;
102169
+ chars += PAGE_BLOCK_CHARS;
102170
+ const call2 = callId(fragment);
102171
+ if (call2) calls2.add(call2);
102172
+ }
102173
+ if (end > start && end < inner.entries.length && inner.blocks[end] === inner.blocks[end - 1]) {
102174
+ const block = inner.blocks[end - 1];
102175
+ let first = end - 1;
102176
+ while (first > start && inner.blocks[first - 1] === block) first--;
102177
+ if (first > start) end = first;
102178
+ else while (end < inner.entries.length && inner.blocks[end] === block) end++;
102179
+ }
102180
+ for (; end < inner.entries.length; end++) {
102181
+ const result3 = resultOf(inner.entries[end]);
102182
+ if (!result3 || !calls2.has(result3)) break;
102183
+ }
102184
+ return { start, end };
102185
+ }
102186
+ function callId(fragment) {
102187
+ const block = fragment.body.kind === "block" ? fragment.body.block : void 0;
102188
+ return block && "toolName" in block ? block.toolUseId : void 0;
102189
+ }
102190
+ function resultOf(fragment) {
102191
+ const block = fragment.body.kind === "block" ? fragment.body.block : void 0;
102192
+ return block && !("toolName" in block) && "toolUseId" in block ? block.toolUseId : void 0;
102193
+ }
102194
+
101973
102195
  // ../../packages/shared/src/transcript-window/select-window.ts
101974
102196
  var DEFAULT_WINDOW_BUDGET = { maxBytes: 128 * 1024, maxFragments: 48, targetChars: 6e3 };
101975
102197
  var MIN_WINDOW_BYTES = MAX_FRAGMENT_BYTES + MAX_META_BYTES + 1024;
@@ -102083,9 +102305,1314 @@ function clamp(value, min, max) {
102083
102305
  return Number.isFinite(value) ? Math.min(max, Math.max(min, Math.floor(value))) : min;
102084
102306
  }
102085
102307
 
102308
+ // ../../packages/chat-core/src/turn-process/process-folds.ts
102309
+ init_content_delta();
102310
+ init_codex_content();
102311
+ init_transcript_window();
102312
+ init_transcript_boundary();
102313
+
102314
+ // ../../packages/shared/src/transcript-segments.ts
102315
+ init_transcript_boundary();
102316
+ init_content_delta();
102317
+ init_codex_async_question();
102318
+ init_codex_content();
102319
+ var cachedSegments = /* @__PURE__ */ new WeakMap();
102320
+ function sliceBlock(block, from, to2) {
102321
+ if (from === 0 && to2 === blockText(block)?.length) return block;
102322
+ if (block.type === "text") return to2 > from ? { ...block, text: block.text.slice(from, to2) } : null;
102323
+ if (block.type === "thinking") return to2 > from || "remoteDetail" in block && block.remoteDetail ? { ...block, thinking: block.thinking.slice(from, to2) } : null;
102324
+ return block;
102325
+ }
102326
+ function sliceItem(item, from, to2) {
102327
+ if (from === 0 && to2 === itemText(item)?.length) return item;
102328
+ if (!("text" in item)) return item;
102329
+ if (to2 <= from && !(item.type === "agent_message" && item.questions?.length) && !(item.type === "reasoning" && item.remoteDetail)) return null;
102330
+ return { ...item, text: item.text.slice(from, to2) };
102331
+ }
102332
+ function contentGroups(content) {
102333
+ const groups = [[]];
102334
+ const owners = /* @__PURE__ */ new Map();
102335
+ for (const block of content) {
102336
+ const parent = "parentToolUseId" in block ? block.parentToolUseId : null;
102337
+ const owner = parent ? owners.get(parent) : isToolResultBlock(block) ? owners.get(block.toolUseId) : void 0;
102338
+ if (owner) {
102339
+ owner.push(block);
102340
+ if (isToolUseBlock(block)) owners.set(block.toolUseId, owner);
102341
+ continue;
102342
+ }
102343
+ if (block.type === "text" && !parent && groups.at(-1).length) groups.push([]);
102344
+ const group = groups.at(-1);
102345
+ group.push(block);
102346
+ if (isToolUseBlock(block)) owners.set(block.toolUseId, group);
102347
+ }
102348
+ return groups;
102349
+ }
102350
+ function itemGroups(items) {
102351
+ const groups = [[]];
102352
+ for (const item of items) {
102353
+ if (item.type === "agent_message" && item.delivery !== "async" && groups.at(-1).length) groups.push([]);
102354
+ groups.at(-1).push(item);
102355
+ }
102356
+ return groups;
102357
+ }
102358
+ function interval(source, previous, next) {
102359
+ const keys = contentKeys(source.content);
102360
+ const parents = new Map(source.content.flatMap((block) => isToolUseBlock(block) && "parentToolUseId" in block && block.parentToolUseId ? [[block.toolUseId, block.parentToolUseId]] : []));
102361
+ const rootOwner = (id) => {
102362
+ const seen = /* @__PURE__ */ new Set();
102363
+ while (parents.has(id) && !seen.has(id)) {
102364
+ seen.add(id);
102365
+ id = parents.get(id);
102366
+ }
102367
+ return `tool:${id}`;
102368
+ };
102369
+ const content = source.content.flatMap((block, index) => {
102370
+ const key = keys[index];
102371
+ const ownerKey = "parentToolUseId" in block && block.parentToolUseId ? rootOwner(block.parentToolUseId) : isToolResultBlock(block) ? rootOwner(block.toolUseId) : key;
102372
+ const start = previous?.content[ownerKey];
102373
+ const end = next?.content[ownerKey];
102374
+ const text2 = blockText(block);
102375
+ if (ownerKey !== key) return start !== void 0 || next && end === void 0 ? [] : [block];
102376
+ if (text2 === void 0) return start !== void 0 || next && end === void 0 ? [] : [block];
102377
+ if (next && end === void 0) return [];
102378
+ if (start === -1) return [];
102379
+ if (start !== void 0 && text2.length <= start) return [];
102380
+ const value = sliceBlock(block, Math.max(0, start ?? 0), Math.min(text2.length, end ?? text2.length));
102381
+ return value ? [value] : [];
102382
+ });
102383
+ const items = (source.metadata?.codex?.items ?? []).flatMap((item) => {
102384
+ const start = previous?.items[item.id];
102385
+ const end = next?.items[item.id];
102386
+ const text2 = itemText(item);
102387
+ if (text2 === void 0) return start !== void 0 || next && end === void 0 ? [] : [item];
102388
+ if (next && end === void 0) return [];
102389
+ if (start === -1) return [];
102390
+ if (start !== void 0 && text2.length <= start) return [];
102391
+ const value = sliceItem(item, Math.max(0, start ?? 0), Math.min(text2.length, end ?? text2.length));
102392
+ return value ? [value] : [];
102393
+ });
102394
+ return { content, items };
102395
+ }
102396
+ function transcriptSegments(messages) {
102397
+ return transcriptView(messages).segments;
102398
+ }
102399
+ function transcriptView(messages) {
102400
+ const displayed = messages.filter((message) => !isDismissedCodexAsyncAnswer(message, messages));
102401
+ const sources = new Set(displayed.map((message) => message.id));
102402
+ const boundaries = /* @__PURE__ */ new Map();
102403
+ const consumed = /* @__PURE__ */ new Set();
102404
+ for (const message of displayed) {
102405
+ const cursor = message.metadata?.transcriptBoundary;
102406
+ if (!cursor || !sources.has(cursor.messageId) || cursor.messageId === message.id) continue;
102407
+ const cutRows = boundaries.get(cursor.messageId) ?? [];
102408
+ cutRows.push(message);
102409
+ boundaries.set(cursor.messageId, cutRows);
102410
+ consumed.add(message.id);
102411
+ }
102412
+ const result3 = [];
102413
+ const rows = [];
102414
+ for (const source of displayed) {
102415
+ if (consumed.has(source.id)) continue;
102416
+ if (source.role !== "assistant" || source.providerId === "system") {
102417
+ const cursor = source.metadata?.transcriptBoundary;
102418
+ result3.push({
102419
+ id: source.id,
102420
+ message: source,
102421
+ source,
102422
+ final: true,
102423
+ anchorId: cursor?.messageId ?? source.id,
102424
+ offset: cursor?.order ?? 0
102425
+ });
102426
+ rows.push({ id: source.id, message: source, source, final: true });
102427
+ continue;
102428
+ }
102429
+ const cuts = (boundaries.get(source.id) ?? []).sort((a, b3) => a.metadata.transcriptBoundary.order - b3.metadata.transcriptBoundary.order);
102430
+ const cached5 = cachedSegments.get(source);
102431
+ if (cached5 && cached5.cuts.length === cuts.length && cached5.cuts.every((cut, index) => cut === cuts[index])) {
102432
+ result3.push(...cached5.segments);
102433
+ rows.push(...cached5.rows);
102434
+ continue;
102435
+ }
102436
+ const cursors = cuts.length ? resolveTranscriptBoundaries(cuts, transcriptLengths(source)) : [];
102437
+ const legacy = isLegacyCodexMessage(source);
102438
+ const segmentOf = (message) => legacy ? withCodexContent(message) : message;
102439
+ const finalResponse = (content) => content.filter((block) => block.type === "text" && block.id === void 0);
102440
+ const sliceOf = (content, items) => segmentOf({
102441
+ ...source,
102442
+ status: "complete",
102443
+ content,
102444
+ metadata: { ...source.metadata, ...legacy ? { codex: { ...source.metadata.codex, items, finalResponse: void 0 } } : {} }
102445
+ });
102446
+ const keys = contentKeys(source.content);
102447
+ const keyByBlock = new Map(source.content.map((block, index) => [block, keys[index]]));
102448
+ const firstResult = result3.length;
102449
+ const firstRow = rows.length;
102450
+ let previous;
102451
+ let firstTurnRow = true;
102452
+ for (let part = 0; part <= cuts.length; part++) {
102453
+ const next = cuts[part];
102454
+ const slice = interval(source, cursors[part - 1], cursors[part]);
102455
+ const groups = legacy ? itemGroups(slice.items).map((items, index, all) => ({
102456
+ items,
102457
+ content: index === all.length - 1 ? finalResponse(slice.content) : []
102458
+ })) : contentGroups(slice.content).map((content) => ({ content, items: [] }));
102459
+ const partSegments = [];
102460
+ for (let group = 0; group < groups.length; group++) {
102461
+ const value = groups[group];
102462
+ if (!value.content.length && !value.items.length && next) continue;
102463
+ const key = value.items[0]?.id ?? keyByBlock.get(value.content[0]) ?? `part-${part}`;
102464
+ const id = result3.length === firstResult ? source.id : previous && group === 0 ? `${source.id}:after:${previous.id}` : `${source.id}:segment:${key}`;
102465
+ const anchorId = source.id;
102466
+ const offset = (previous ? previous.metadata.transcriptBoundary.order + 0.1 : 0) + group / (groups.length + 1) * 0.5;
102467
+ const segment = { id, source, final: false, anchorId, offset, message: sliceOf(value.content, value.items) };
102468
+ result3.push(segment);
102469
+ partSegments.push({ segment, opens: { block: value.content[0], itemId: value.items[0]?.id } });
102470
+ }
102471
+ if (partSegments.length) {
102472
+ const [first, ...rest] = partSegments;
102473
+ const message = rest.length ? sliceOf(legacy ? finalResponse(slice.content) : slice.content, slice.items) : first.segment.message;
102474
+ const anchors = /* @__PURE__ */ new Map();
102475
+ for (const { segment, opens } of rest) {
102476
+ const block = legacy ? message.content.find((candidate) => "id" in candidate && candidate.id === opens.itemId) : opens.block;
102477
+ if (block) anchors.set(block, segment.id);
102478
+ }
102479
+ const following = next ? interval(source, cursors[part]) : void 0;
102480
+ rows.push({
102481
+ id: first.segment.id,
102482
+ message,
102483
+ source,
102484
+ final: false,
102485
+ first: firstTurnRow,
102486
+ ...anchors.size ? { anchors } : {},
102487
+ ...following ? { following: sliceOf(following.content, following.items) } : {}
102488
+ });
102489
+ firstTurnRow = false;
102490
+ }
102491
+ if (next) {
102492
+ result3.push({
102493
+ id: next.id,
102494
+ message: next,
102495
+ source: next,
102496
+ final: true,
102497
+ anchorId: source.id,
102498
+ offset: next.metadata.transcriptBoundary.order
102499
+ });
102500
+ rows.push({ id: next.id, message: next, source: next, final: true });
102501
+ }
102502
+ previous = next;
102503
+ }
102504
+ const last = result3.findLast((segment) => segment.source === source);
102505
+ const lastRow = rows.findLast((row2) => row2.source === source);
102506
+ if (last) {
102507
+ const shared = lastRow?.message === last.message;
102508
+ last.final = true;
102509
+ last.message = segmentOf({ ...last.message, status: source.status });
102510
+ if (shared) lastRow.message = last.message;
102511
+ }
102512
+ if (lastRow) {
102513
+ lastRow.final = true;
102514
+ if (lastRow.message.status !== source.status) lastRow.message = segmentOf({ ...lastRow.message, status: source.status });
102515
+ }
102516
+ cachedSegments.set(source, { cuts, segments: result3.slice(firstResult), rows: rows.slice(firstRow) });
102517
+ }
102518
+ return { segments: result3, rows };
102519
+ }
102520
+
102521
+ // ../../packages/chat-core/src/turn-process/compact-mode.ts
102522
+ init_suggested_task();
102523
+ function isPinnedToolName(toolName, ports2) {
102524
+ return ports2.isWidgetShowTool(toolName) || toolName === "AskUserQuestion" || toolName.endsWith("__AskUserQuestion") || isSuggestTaskTool(toolName);
102525
+ }
102526
+ var MIN_PROCESS_SEGMENTS_TO_COLLAPSE = 3;
102527
+ function compactTurnRuns(items, isPinned, neighbors) {
102528
+ if (!neighbors) return partitionTurnForCompactMode(items, isPinned);
102529
+ return partitionTurnForCompactMode(
102530
+ items,
102531
+ isPinned,
102532
+ neighbors.following?.some(isPinned) ?? false,
102533
+ neighbors.source?.some(isPinned) ?? false
102534
+ );
102535
+ }
102536
+ function partitionTurnForCompactMode(items, isPinned, hasFollowingPinned = false, hasPrecedingPinned = false) {
102537
+ if (items.length === 0) return [];
102538
+ let lastPinned = -1;
102539
+ for (let i = items.length - 1; i >= 0; i--) {
102540
+ if (isPinned(items[i])) {
102541
+ lastPinned = i;
102542
+ break;
102543
+ }
102544
+ }
102545
+ if (lastPinned < 0) return [{ collapsible: hasFollowingPinned || !hasPrecedingPinned, start: 0, items: items.slice() }];
102546
+ const runs = [];
102547
+ for (let i = 0; i < items.length; i++) {
102548
+ const collapsible = (hasFollowingPinned || i < lastPinned) && !isPinned(items[i]);
102549
+ const last = runs[runs.length - 1];
102550
+ if (last && last.collapsible === collapsible) last.items.push(items[i]);
102551
+ else runs.push({ collapsible, start: i, items: [items[i]] });
102552
+ }
102553
+ return runs;
102554
+ }
102555
+ function collapsibleItems(runs) {
102556
+ return runs.flatMap((run) => run.collapsible ? run.items : []);
102557
+ }
102558
+ function isClaudePinnedSegment(seg, ports2) {
102559
+ if (seg.kind === "subagent" || seg.kind === "workflow") return true;
102560
+ if (seg.kind !== "block" || !seg.block) return false;
102561
+ if (seg.block.type === "text" || seg.block.type === "insight" || seg.block.type === "plan") return true;
102562
+ return seg.block.type === "tool_use" && (Boolean(seg.block.app) || isPinnedToolName(seg.block.toolName ?? "", ports2));
102563
+ }
102564
+ function isVisibleClaudeProcessSegment(seg, opts) {
102565
+ const { toolResultAt, isHiddenTool } = opts;
102566
+ if (seg.kind === "thinking" || seg.kind === "subagent" || seg.kind === "workflow") {
102567
+ return true;
102568
+ }
102569
+ if (seg.kind === "tools" || seg.kind === "app-tools") {
102570
+ return (seg.blocks ?? []).some(
102571
+ (b3) => b3.type === "tool_use" && !isHiddenTool(b3.toolName ?? "", toolResultAt(b3.toolUseId ?? ""))
102572
+ );
102573
+ }
102574
+ if (seg.kind === "block" && seg.block) {
102575
+ const b3 = seg.block;
102576
+ if (b3.type === "tool_result") return false;
102577
+ if (b3.type === "tool_use") {
102578
+ return !isHiddenTool(b3.toolName ?? "", toolResultAt(b3.toolUseId ?? ""));
102579
+ }
102580
+ return true;
102581
+ }
102582
+ return true;
102583
+ }
102584
+ function countVisibleClaudeProcessSegments(segs, opts) {
102585
+ let n = 0;
102586
+ for (const seg of segs) {
102587
+ if (seg.kind === "block" && seg.block?.fold) n += seg.block.fold.segments;
102588
+ else if (isVisibleClaudeProcessSegment(seg, opts)) n += 1;
102589
+ }
102590
+ return n;
102591
+ }
102592
+
102593
+ // ../../packages/chat-core/src/turn-process/group-content.ts
102594
+ init_content_delta();
102595
+ init_jev_run_result_shape();
102596
+ init_codex_command_actions();
102597
+ var COLLAPSIBLE_TOOLS = /* @__PURE__ */ new Set(["Read", "Glob", "Grep", "WebSearch", "WebFetch"]);
102598
+ function runIdIn(text2) {
102599
+ const match = text2 ? /"runId"\s*:\s*"([^"]+)"/.exec(text2) : null;
102600
+ return match?.[1] ?? null;
102601
+ }
102602
+ function groupContentPresenter(content, ports2) {
102603
+ const toolNameMap = /* @__PURE__ */ new Map();
102604
+ const toolResultMap = /* @__PURE__ */ new Map();
102605
+ const timedOutToolIds = /* @__PURE__ */ new Set();
102606
+ const errorToolIds = /* @__PURE__ */ new Set();
102607
+ const outputPathMap = /* @__PURE__ */ new Map();
102608
+ const bashEditDiffMap = /* @__PURE__ */ new Map();
102609
+ const exitCodeMap = /* @__PURE__ */ new Map();
102610
+ const resultTitleMap = /* @__PURE__ */ new Map();
102611
+ const toolAppMap = /* @__PURE__ */ new Map();
102612
+ const taskToolUseIds = /* @__PURE__ */ new Set();
102613
+ const collapsibleIds = /* @__PURE__ */ new Set();
102614
+ for (const block of content) {
102615
+ if (block.type === "tool_use") {
102616
+ toolNameMap.set(block.toolUseId, block.toolName);
102617
+ if (ports2.isSubagentToolName(block.toolName)) taskToolUseIds.add(block.toolUseId);
102618
+ if (COLLAPSIBLE_TOOLS.has(block.toolName) || block.toolName === "Bash" && isReadOnlyParsedCommand(block.toolUseId, block.input)) {
102619
+ collapsibleIds.add(block.toolUseId);
102620
+ }
102621
+ } else if (isToolResultBlock(block)) {
102622
+ if (block.summary) toolResultMap.set(block.toolUseId, block.summary);
102623
+ if ("isTimedOut" in block && block.isTimedOut) timedOutToolIds.add(block.toolUseId);
102624
+ if ("isError" in block && block.isError) errorToolIds.add(block.toolUseId);
102625
+ if ("outputPath" in block && block.outputPath) outputPathMap.set(block.toolUseId, block.outputPath);
102626
+ if ("bashEditDiff" in block && block.bashEditDiff) bashEditDiffMap.set(block.toolUseId, block.bashEditDiff);
102627
+ if ("exitCode" in block && block.exitCode !== void 0) exitCodeMap.set(block.toolUseId, block.exitCode);
102628
+ if ("resultTitle" in block && block.resultTitle) resultTitleMap.set(block.toolUseId, block.resultTitle);
102629
+ if ("app" in block && block.app) toolAppMap.set(block.toolUseId, block.app);
102630
+ }
102631
+ }
102632
+ const appToolIdToAppId = /* @__PURE__ */ new Map();
102633
+ for (const block of content) {
102634
+ if (block.type !== "tool_use") continue;
102635
+ const resolved = ports2.resolveAppTool(block.toolName, block.input);
102636
+ if (!resolved || resolved.standalone || !resolved.groupable) continue;
102637
+ appToolIdToAppId.set(block.toolUseId, resolved.appId);
102638
+ }
102639
+ const runOwnerByRunId = /* @__PURE__ */ new Map();
102640
+ const runContinuationOwner = /* @__PURE__ */ new Map();
102641
+ const runContinuations = /* @__PURE__ */ new Map();
102642
+ for (const block of content) {
102643
+ if (block.type !== "tool_use" || !isJevRunToolName(block.toolName)) continue;
102644
+ const resumes = runIdIn(block.input);
102645
+ const owner = resumes ? runOwnerByRunId.get(resumes) : void 0;
102646
+ if (owner) {
102647
+ runContinuationOwner.set(block.toolUseId, owner);
102648
+ runContinuations.set(owner, [...runContinuations.get(owner) ?? [], block]);
102649
+ continue;
102650
+ }
102651
+ const started = runIdIn(toolResultMap.get(block.toolUseId));
102652
+ if (started && !runOwnerByRunId.has(started)) runOwnerByRunId.set(started, block.toolUseId);
102653
+ }
102654
+ const segments = [];
102655
+ let group = [];
102656
+ let groupStart = 0;
102657
+ let appGroup = [];
102658
+ let appGroupId = null;
102659
+ let appGroupStart = 0;
102660
+ const activeSubagents = /* @__PURE__ */ new Map();
102661
+ const activeWorkflows = /* @__PURE__ */ new Map();
102662
+ const agentToParent = /* @__PURE__ */ new Map();
102663
+ const topAncestorSubagent = (parentId) => {
102664
+ let current = parentId;
102665
+ const seen = /* @__PURE__ */ new Set();
102666
+ while (current && agentToParent.has(current) && !seen.has(current)) {
102667
+ seen.add(current);
102668
+ const parent = agentToParent.get(current) ?? null;
102669
+ if (parent == null) break;
102670
+ current = parent;
102671
+ }
102672
+ return current && activeSubagents.has(current) ? current : null;
102673
+ };
102674
+ const flush = () => {
102675
+ if (group.length === 0) return;
102676
+ segments.push({ kind: "tools", blocks: group, startIndex: groupStart });
102677
+ group = [];
102678
+ };
102679
+ const flushAppGroup = () => {
102680
+ if (appGroup.length === 0) return;
102681
+ segments.push({
102682
+ kind: "app-tools",
102683
+ appId: appGroupId,
102684
+ blocks: appGroup,
102685
+ startIndex: appGroupStart
102686
+ });
102687
+ appGroup = [];
102688
+ appGroupId = null;
102689
+ };
102690
+ for (let index = 0; index < content.length; index++) {
102691
+ const block = content[index];
102692
+ const parentId = "parentToolUseId" in block ? block.parentToolUseId ?? null : null;
102693
+ if (parentId) {
102694
+ if (block.type === "tool_use" && ports2.isSubagentToolName(block.toolName)) {
102695
+ agentToParent.set(block.toolUseId, parentId);
102696
+ }
102697
+ const top = topAncestorSubagent(parentId);
102698
+ if (top) {
102699
+ activeSubagents.get(top).childBlocks.push(block);
102700
+ continue;
102701
+ }
102702
+ }
102703
+ if (isToolResultBlock(block) && taskToolUseIds.has(block.toolUseId) && activeSubagents.has(block.toolUseId)) {
102704
+ activeSubagents.get(block.toolUseId).resultBlock = block;
102705
+ continue;
102706
+ }
102707
+ if (block.type === "tool_use" && ports2.isSubagentToolName(block.toolName)) {
102708
+ flush();
102709
+ flushAppGroup();
102710
+ const segment = {
102711
+ kind: "subagent",
102712
+ taskBlock: block,
102713
+ childBlocks: [],
102714
+ startIndex: index
102715
+ };
102716
+ segments.push(segment);
102717
+ activeSubagents.set(block.toolUseId, segment);
102718
+ agentToParent.set(block.toolUseId, null);
102719
+ continue;
102720
+ }
102721
+ if (isToolResultBlock(block) && activeWorkflows.has(block.toolUseId)) {
102722
+ activeWorkflows.get(block.toolUseId).resultBlock = block;
102723
+ activeWorkflows.delete(block.toolUseId);
102724
+ continue;
102725
+ }
102726
+ if ((block.type === "tool_use" || isToolResultBlock(block)) && runContinuationOwner.has(block.toolUseId)) continue;
102727
+ if (block.type === "tool_use" && block.toolName === "Workflow" && !ports2.isWorkflowSmokeCheck(block.input)) {
102728
+ flush();
102729
+ flushAppGroup();
102730
+ const segment = {
102731
+ kind: "workflow",
102732
+ toolBlock: block,
102733
+ startIndex: index
102734
+ };
102735
+ segments.push(segment);
102736
+ activeWorkflows.set(block.toolUseId, segment);
102737
+ continue;
102738
+ }
102739
+ if (block.type === "tool_use" && appToolIdToAppId.has(block.toolUseId)) {
102740
+ flush();
102741
+ const blockAppId = appToolIdToAppId.get(block.toolUseId);
102742
+ if (appGroupId !== blockAppId) {
102743
+ flushAppGroup();
102744
+ appGroupId = blockAppId;
102745
+ appGroupStart = index;
102746
+ }
102747
+ appGroup.push(block);
102748
+ continue;
102749
+ }
102750
+ if (isToolResultBlock(block) && appToolIdToAppId.has(block.toolUseId)) {
102751
+ appGroup.push(block);
102752
+ continue;
102753
+ }
102754
+ if (isToolResultBlock(block) && toolNameMap.has(block.toolUseId)) continue;
102755
+ flushAppGroup();
102756
+ if (block.type === "tool_use" && collapsibleIds.has(block.toolUseId)) {
102757
+ if (group.length === 0) groupStart = index;
102758
+ group.push(block);
102759
+ } else if (block.type === "tool_use" && ports2.isHiddenToolBlock(block.toolName, toolResultMap.get(block.toolUseId))) {
102760
+ flush();
102761
+ } else if (block.type === "thinking") {
102762
+ flush();
102763
+ const last = segments[segments.length - 1];
102764
+ if (last?.kind === "thinking") last.blocks.push(block);
102765
+ else segments.push({ kind: "thinking", blocks: [block], startIndex: index });
102766
+ } else {
102767
+ flush();
102768
+ segments.push({ kind: "block", block, index });
102769
+ }
102770
+ }
102771
+ flush();
102772
+ flushAppGroup();
102773
+ return {
102774
+ segments,
102775
+ toolNameMap,
102776
+ toolResultMap,
102777
+ timedOutToolIds,
102778
+ errorToolIds,
102779
+ outputPathMap,
102780
+ bashEditDiffMap,
102781
+ exitCodeMap,
102782
+ resultTitleMap,
102783
+ toolAppMap,
102784
+ runContinuations
102785
+ };
102786
+ }
102787
+
102788
+ // ../../packages/chat-core/src/turn-process/media-tools.ts
102789
+ init_codex_content();
102790
+
102791
+ // ../../packages/shared/src/generative-ui/native-widgets.ts
102792
+ var NATIVE_TEMPLATE_PREFIX = "@native/";
102793
+ var NATIVE_WIDGET_TYPES = ["image-gallery", "video-gallery", "files-previewer"];
102794
+ function isNativeTemplateId(template) {
102795
+ return template.startsWith(NATIVE_TEMPLATE_PREFIX);
102796
+ }
102797
+ function nativeTypeFromTemplateId(template) {
102798
+ if (!isNativeTemplateId(template)) return null;
102799
+ const suffix = template.slice(NATIVE_TEMPLATE_PREFIX.length);
102800
+ return NATIVE_WIDGET_TYPES.includes(suffix) ? suffix : null;
102801
+ }
102802
+ function renderableItems(value) {
102803
+ if (!Array.isArray(value)) return [];
102804
+ return value.filter((item) => {
102805
+ if (!item || typeof item !== "object") return false;
102806
+ const path = item.savedPath;
102807
+ return typeof path === "string" && path.trim().length > 0;
102808
+ });
102809
+ }
102810
+ function parseNativeWidgetResult(resultText) {
102811
+ if (!resultText) return null;
102812
+ let parsed;
102813
+ try {
102814
+ parsed = JSON.parse(resultText);
102815
+ } catch {
102816
+ return null;
102817
+ }
102818
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
102819
+ const record13 = parsed;
102820
+ if (record13.kind !== "native") return null;
102821
+ const nativeType = typeof record13.nativeType === "string" ? nativeTypeFromTemplateId(NATIVE_TEMPLATE_PREFIX + record13.nativeType) : null;
102822
+ if (!nativeType) return null;
102823
+ const title2 = typeof record13.title === "string" ? record13.title : "";
102824
+ if (nativeType === "image-gallery") {
102825
+ const images = renderableItems(record13.images);
102826
+ return images.length > 0 ? { kind: "native", nativeType, title: title2, images } : null;
102827
+ }
102828
+ if (nativeType === "files-previewer") {
102829
+ if (record13.images !== void 0 || record13.videos !== void 0) return null;
102830
+ const files = previewerFiles(record13.files);
102831
+ const root = typeof record13.root === "string" ? record13.root : "";
102832
+ return files.length > 0 && root ? { kind: "native", nativeType, title: title2, root, files } : null;
102833
+ }
102834
+ const videos = renderableItems(record13.videos);
102835
+ return videos.length > 0 ? { kind: "native", nativeType, title: title2, videos } : null;
102836
+ }
102837
+ var PREVIEWER_KINDS = /* @__PURE__ */ new Set([
102838
+ "image",
102839
+ "pdf",
102840
+ "video",
102841
+ "audio",
102842
+ "model",
102843
+ "markdown",
102844
+ "notebook",
102845
+ "text",
102846
+ "unpreviewable",
102847
+ "missing"
102848
+ ]);
102849
+ function previewerFiles(value) {
102850
+ if (!Array.isArray(value)) return [];
102851
+ const files = [];
102852
+ for (const item of value) {
102853
+ if (!item || typeof item !== "object") continue;
102854
+ const r = item;
102855
+ if (typeof r.path !== "string" || typeof r.absolutePath !== "string" || typeof r.name !== "string") continue;
102856
+ if (typeof r.kind !== "string" || !PREVIEWER_KINDS.has(r.kind)) continue;
102857
+ files.push({
102858
+ path: r.path,
102859
+ absolutePath: r.absolutePath,
102860
+ name: r.name,
102861
+ kind: r.kind,
102862
+ ...typeof r.size === "number" && Number.isFinite(r.size) ? { size: r.size } : {},
102863
+ ...typeof r.reason === "string" ? { reason: r.reason } : {},
102864
+ ...typeof r.note === "string" && r.note ? { note: r.note } : {}
102865
+ });
102866
+ }
102867
+ return files;
102868
+ }
102869
+
102870
+ // ../../packages/chat-core/src/turn-process/media-tools.ts
102871
+ init_tool_ui();
102872
+ init_media_predicates();
102873
+ var MEDIA_GENERATE_IMAGE_TOOL = "mcp__superone__media_generate_image";
102874
+ var WIDGET_SHOW_TOOL = "mcp__superone__widget_show";
102875
+ var GROK_IMAGE_GEN_TOOLS = /* @__PURE__ */ new Set(["ImageGen", "ImageEdit", "image_gen", "image_edit"]);
102876
+ var GROK_VIDEO_GEN_TOOLS = /* @__PURE__ */ new Set([
102877
+ "ImageToVideo",
102878
+ "ReferenceToVideo",
102879
+ "image_to_video",
102880
+ "reference_to_video"
102881
+ ]);
102882
+ var GROK_MEDIA_OUTPUT_TYPES = /* @__PURE__ */ new Set(["ImageGen", "ImageEdit", "ImageToVideo", "ReferenceToVideo"]);
102883
+ function isMediaGenerateImageTool(toolName) {
102884
+ return toolName === MEDIA_GENERATE_IMAGE_TOOL || GROK_IMAGE_GEN_TOOLS.has(toolName);
102885
+ }
102886
+ function isGrokVideoGenTool(toolName) {
102887
+ return GROK_VIDEO_GEN_TOOLS.has(toolName);
102888
+ }
102889
+ function isWidgetShowTool(toolName) {
102890
+ return toolName === WIDGET_SHOW_TOOL;
102891
+ }
102892
+ function nativeWidgetImages(resultText) {
102893
+ return parseNativeWidgetResult(resultText)?.images ?? [];
102894
+ }
102895
+ function nativeWidgetVideos(resultText) {
102896
+ return parseNativeWidgetResult(resultText)?.videos ?? [];
102897
+ }
102898
+ function coerceGenerationResult(parsed) {
102899
+ const saved = toSavedPaths(parsed);
102900
+ if (saved.length > 0) {
102901
+ return {
102902
+ ...parsed,
102903
+ status: parsed.status === "error" ? "error" : parsed.status ?? "generated",
102904
+ savedPaths: saved
102905
+ };
102906
+ }
102907
+ const path = typeof parsed.path === "string" ? parsed.path.trim() : "";
102908
+ if (path) {
102909
+ const type = typeof parsed.type === "string" ? parsed.type : void 0;
102910
+ if (type && !GROK_MEDIA_OUTPUT_TYPES.has(type)) {
102911
+ if (!/\.(png|jpe?g|gif|webp|bmp|mp4|webm|mov)$/i.test(path) && !path.includes("/images/")) {
102912
+ return parsed;
102913
+ }
102914
+ }
102915
+ return {
102916
+ status: "generated",
102917
+ savedPaths: [path],
102918
+ provider: parsed.provider ?? "grok",
102919
+ model: parsed.model,
102920
+ warnings: parsed.warnings,
102921
+ generationId: parsed.generationId
102922
+ };
102923
+ }
102924
+ return parsed;
102925
+ }
102926
+ function parseGenerationResult(resultText) {
102927
+ if (!resultText) return null;
102928
+ try {
102929
+ const parsed = JSON.parse(resultText);
102930
+ if (!parsed || typeof parsed !== "object") return null;
102931
+ return coerceGenerationResult(parsed);
102932
+ } catch {
102933
+ return null;
102934
+ }
102935
+ }
102936
+ function toSavedPaths(parsed) {
102937
+ return Array.isArray(parsed.savedPaths) ? parsed.savedPaths.filter((p3) => typeof p3 === "string") : [];
102938
+ }
102939
+ function isSuccessfulGenerationResult(resultText) {
102940
+ const parsed = parseGenerationResult(resultText);
102941
+ if (!parsed || parsed.status === "error") return false;
102942
+ return toSavedPaths(parsed).length > 0;
102943
+ }
102944
+ function isVideoStatusStillRunning(resultText) {
102945
+ return parseGenerationResult(resultText)?.status === "running";
102946
+ }
102947
+ function isHiddenToolBlock(toolName, result3) {
102948
+ if (isAlwaysHiddenToolName(toolName)) return true;
102949
+ if (toolName === CODEX_AGENT_WAIT_TOOL) return result3 !== void 0;
102950
+ if (isWidgetShowTool(toolName)) return nativeWidgetImages(result3).length > 0 || nativeWidgetVideos(result3).length > 0;
102951
+ if (isMediaGenerateImageTool(toolName)) return !result3 || isSuccessfulGenerationResult(result3);
102952
+ if (isGrokVideoGenTool(toolName)) return !result3 || isSuccessfulGenerationResult(result3);
102953
+ if (isMediaVideoStatusTool(toolName)) {
102954
+ return !result3 || isVideoStatusStillRunning(result3) || isSuccessfulGenerationResult(result3);
102955
+ }
102956
+ return false;
102957
+ }
102958
+ function isTurnGallerySourceTool(toolName) {
102959
+ return toolName === CODEX_IMAGE_GENERATION_TOOL || isWidgetShowTool(toolName) || isMediaGenerateImageTool(toolName) || isMediaGenerateVideoTool(toolName) || isMediaVideoStatusTool(toolName) || isGrokVideoGenTool(toolName);
102960
+ }
102961
+
102962
+ // ../../packages/chat-core/src/turn-process/portable.ts
102963
+ init_tool_ui();
102964
+ function isOffTranscript(block, failed2) {
102965
+ if (block.type === "text") return Boolean(block.codexAsyncQuestions?.length);
102966
+ return failed2 && block.type === "notice" && block.level === "error";
102967
+ }
102968
+ function isOffTranscriptBlock(block, message) {
102969
+ return isOffTranscript(block, message.status === "error");
102970
+ }
102971
+ function turnDisplayContent(message) {
102972
+ const failed2 = message.status === "error";
102973
+ return message.content.some((block) => isOffTranscript(block, failed2)) ? message.content.filter((block) => !isOffTranscript(block, failed2)) : message.content;
102974
+ }
102975
+ function portableToolBlock(block) {
102976
+ return "toolName" in block && block.type !== "tool_use" ? { ...block, type: "tool_use" } : block;
102977
+ }
102978
+ function portableToolBlocks(content) {
102979
+ return content.map(portableToolBlock);
102980
+ }
102981
+ function parseRecord(value) {
102982
+ try {
102983
+ const parsed = JSON.parse(value);
102984
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
102985
+ } catch {
102986
+ return {};
102987
+ }
102988
+ }
102989
+ function isWorkflowSmokeCheck(input) {
102990
+ const parsed = parseRecord(input);
102991
+ return parsed.validate_only === true || parsed.validateOnly === true || /"(?:validate_only|validateOnly)"\s*:\s*true/.test(input);
102992
+ }
102993
+ function isPortableWidgetShowTool(toolName) {
102994
+ return toolName === "widget_show" || toolName.endsWith("__widget_show");
102995
+ }
102996
+ var PORTABLE_GROUP_PORTS = {
102997
+ isSubagentToolName,
102998
+ isWorkflowSmokeCheck,
102999
+ isHiddenToolBlock,
103000
+ resolveAppTool: () => null
103001
+ };
103002
+ function isPortablePinnedSegment(segment) {
103003
+ return isClaudePinnedSegment(segment, { isWidgetShowTool: isPortableWidgetShowTool });
103004
+ }
103005
+
103006
+ // ../../packages/chat-core/src/turn-process/process-stats.ts
103007
+ init_tool_ui();
103008
+
103009
+ // ../../node_modules/diff/libesm/diff/base.js
103010
+ var Diff2 = class {
103011
+ diff(oldStr, newStr, options = {}) {
103012
+ let callback;
103013
+ if (typeof options === "function") {
103014
+ callback = options;
103015
+ options = {};
103016
+ } else if ("callback" in options) {
103017
+ callback = options.callback;
103018
+ }
103019
+ const oldString = this.castInput(oldStr, options);
103020
+ const newString = this.castInput(newStr, options);
103021
+ const oldTokens = this.removeEmpty(this.tokenize(oldString, options));
103022
+ const newTokens = this.removeEmpty(this.tokenize(newString, options));
103023
+ return this.diffWithOptionsObj(oldTokens, newTokens, options, callback);
103024
+ }
103025
+ diffWithOptionsObj(oldTokens, newTokens, options, callback) {
103026
+ var _a3;
103027
+ const done = (value) => {
103028
+ value = this.postProcess(value, options);
103029
+ if (callback) {
103030
+ setTimeout(function() {
103031
+ callback(value);
103032
+ }, 0);
103033
+ return void 0;
103034
+ } else {
103035
+ return value;
103036
+ }
103037
+ };
103038
+ const newLen = newTokens.length, oldLen = oldTokens.length;
103039
+ let editLength = 1;
103040
+ let maxEditLength = newLen + oldLen;
103041
+ if (options.maxEditLength != null) {
103042
+ maxEditLength = Math.min(maxEditLength, options.maxEditLength);
103043
+ }
103044
+ const maxExecutionTime = (_a3 = options.timeout) !== null && _a3 !== void 0 ? _a3 : Infinity;
103045
+ const abortAfterTimestamp = Date.now() + maxExecutionTime;
103046
+ const bestPath = [{ oldPos: -1, lastComponent: void 0 }];
103047
+ let newPos = this.extractCommon(bestPath[0], newTokens, oldTokens, 0, options);
103048
+ if (bestPath[0].oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
103049
+ return done(this.buildValues(bestPath[0].lastComponent, newTokens, oldTokens));
103050
+ }
103051
+ let minDiagonalToConsider = -Infinity, maxDiagonalToConsider = Infinity;
103052
+ const execEditLength = () => {
103053
+ for (let diagonalPath = Math.max(minDiagonalToConsider, -editLength); diagonalPath <= Math.min(maxDiagonalToConsider, editLength); diagonalPath += 2) {
103054
+ let basePath;
103055
+ const removePath = bestPath[diagonalPath - 1], addPath = bestPath[diagonalPath + 1];
103056
+ if (removePath) {
103057
+ bestPath[diagonalPath - 1] = void 0;
103058
+ }
103059
+ let canAdd = false;
103060
+ if (addPath) {
103061
+ const addPathNewPos = addPath.oldPos - diagonalPath;
103062
+ canAdd = addPath && 0 <= addPathNewPos && addPathNewPos < newLen;
103063
+ }
103064
+ const canRemove = removePath && removePath.oldPos + 1 < oldLen;
103065
+ if (!canAdd && !canRemove) {
103066
+ bestPath[diagonalPath] = void 0;
103067
+ continue;
103068
+ }
103069
+ if (!canRemove || canAdd && removePath.oldPos < addPath.oldPos) {
103070
+ basePath = this.addToPath(addPath, true, false, 0, options);
103071
+ } else {
103072
+ basePath = this.addToPath(removePath, false, true, 1, options);
103073
+ }
103074
+ newPos = this.extractCommon(basePath, newTokens, oldTokens, diagonalPath, options);
103075
+ if (basePath.oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
103076
+ return done(this.buildValues(basePath.lastComponent, newTokens, oldTokens)) || true;
103077
+ } else {
103078
+ bestPath[diagonalPath] = basePath;
103079
+ if (basePath.oldPos + 1 >= oldLen) {
103080
+ maxDiagonalToConsider = Math.min(maxDiagonalToConsider, diagonalPath - 1);
103081
+ }
103082
+ if (newPos + 1 >= newLen) {
103083
+ minDiagonalToConsider = Math.max(minDiagonalToConsider, diagonalPath + 1);
103084
+ }
103085
+ }
103086
+ }
103087
+ editLength++;
103088
+ };
103089
+ if (callback) {
103090
+ (function exec2() {
103091
+ setTimeout(function() {
103092
+ if (editLength > maxEditLength || Date.now() > abortAfterTimestamp) {
103093
+ return callback(void 0);
103094
+ }
103095
+ if (!execEditLength()) {
103096
+ exec2();
103097
+ }
103098
+ }, 0);
103099
+ })();
103100
+ } else {
103101
+ while (editLength <= maxEditLength && Date.now() <= abortAfterTimestamp) {
103102
+ const ret = execEditLength();
103103
+ if (ret) {
103104
+ return ret;
103105
+ }
103106
+ }
103107
+ }
103108
+ }
103109
+ addToPath(path, added, removed, oldPosInc, options) {
103110
+ const last = path.lastComponent;
103111
+ if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
103112
+ return {
103113
+ oldPos: path.oldPos + oldPosInc,
103114
+ lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
103115
+ };
103116
+ } else {
103117
+ return {
103118
+ oldPos: path.oldPos + oldPosInc,
103119
+ lastComponent: { count: 1, added, removed, previousComponent: last }
103120
+ };
103121
+ }
103122
+ }
103123
+ extractCommon(basePath, newTokens, oldTokens, diagonalPath, options) {
103124
+ const newLen = newTokens.length, oldLen = oldTokens.length;
103125
+ let oldPos = basePath.oldPos, newPos = oldPos - diagonalPath, commonCount = 0;
103126
+ while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(oldTokens[oldPos + 1], newTokens[newPos + 1], options)) {
103127
+ newPos++;
103128
+ oldPos++;
103129
+ commonCount++;
103130
+ if (options.oneChangePerToken) {
103131
+ basePath.lastComponent = { count: 1, previousComponent: basePath.lastComponent, added: false, removed: false };
103132
+ }
103133
+ }
103134
+ if (commonCount && !options.oneChangePerToken) {
103135
+ basePath.lastComponent = { count: commonCount, previousComponent: basePath.lastComponent, added: false, removed: false };
103136
+ }
103137
+ basePath.oldPos = oldPos;
103138
+ return newPos;
103139
+ }
103140
+ equals(left, right, options) {
103141
+ if (options.comparator) {
103142
+ return options.comparator(left, right);
103143
+ } else {
103144
+ return left === right || !!options.ignoreCase && left.toLowerCase() === right.toLowerCase();
103145
+ }
103146
+ }
103147
+ removeEmpty(array2) {
103148
+ const ret = [];
103149
+ for (let i = 0; i < array2.length; i++) {
103150
+ if (array2[i]) {
103151
+ ret.push(array2[i]);
103152
+ }
103153
+ }
103154
+ return ret;
103155
+ }
103156
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
103157
+ castInput(value, options) {
103158
+ return value;
103159
+ }
103160
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
103161
+ tokenize(value, options) {
103162
+ return Array.from(value);
103163
+ }
103164
+ join(chars) {
103165
+ return chars.join("");
103166
+ }
103167
+ postProcess(changeObjects, options) {
103168
+ return changeObjects;
103169
+ }
103170
+ get useLongestToken() {
103171
+ return false;
103172
+ }
103173
+ buildValues(lastComponent, newTokens, oldTokens) {
103174
+ const components = [];
103175
+ let nextComponent;
103176
+ while (lastComponent) {
103177
+ components.push(lastComponent);
103178
+ nextComponent = lastComponent.previousComponent;
103179
+ delete lastComponent.previousComponent;
103180
+ lastComponent = nextComponent;
103181
+ }
103182
+ components.reverse();
103183
+ const componentLen = components.length;
103184
+ let componentPos = 0, newPos = 0, oldPos = 0;
103185
+ for (; componentPos < componentLen; componentPos++) {
103186
+ const component = components[componentPos];
103187
+ if (!component.removed) {
103188
+ if (!component.added && this.useLongestToken) {
103189
+ let value = newTokens.slice(newPos, newPos + component.count);
103190
+ value = value.map(function(value2, i) {
103191
+ const oldValue = oldTokens[oldPos + i];
103192
+ return oldValue.length > value2.length ? oldValue : value2;
103193
+ });
103194
+ component.value = this.join(value);
103195
+ } else {
103196
+ component.value = this.join(newTokens.slice(newPos, newPos + component.count));
103197
+ }
103198
+ newPos += component.count;
103199
+ if (!component.added) {
103200
+ oldPos += component.count;
103201
+ }
103202
+ } else {
103203
+ component.value = this.join(oldTokens.slice(oldPos, oldPos + component.count));
103204
+ oldPos += component.count;
103205
+ }
103206
+ }
103207
+ return components;
103208
+ }
103209
+ };
103210
+
103211
+ // ../../node_modules/diff/libesm/diff/line.js
103212
+ var LineDiff2 = class extends Diff2 {
103213
+ constructor() {
103214
+ super(...arguments);
103215
+ this.tokenize = tokenize2;
103216
+ }
103217
+ equals(left, right, options) {
103218
+ if (options.ignoreWhitespace) {
103219
+ if (!options.newlineIsToken || !left.includes("\n")) {
103220
+ left = left.trim();
103221
+ }
103222
+ if (!options.newlineIsToken || !right.includes("\n")) {
103223
+ right = right.trim();
103224
+ }
103225
+ } else if (options.ignoreNewlineAtEof && !options.newlineIsToken) {
103226
+ if (left.endsWith("\n")) {
103227
+ left = left.slice(0, -1);
103228
+ }
103229
+ if (right.endsWith("\n")) {
103230
+ right = right.slice(0, -1);
103231
+ }
103232
+ }
103233
+ return super.equals(left, right, options);
103234
+ }
103235
+ };
103236
+ var lineDiff2 = new LineDiff2();
103237
+ function diffLines2(oldStr, newStr, options) {
103238
+ return lineDiff2.diff(oldStr, newStr, options);
103239
+ }
103240
+ function tokenize2(value, options) {
103241
+ if (options.stripTrailingCr) {
103242
+ value = value.replace(/\r\n/g, "\n");
103243
+ }
103244
+ const retLines = [], linesAndNewlines = value.split(/(\n|\r\n)/);
103245
+ if (!linesAndNewlines[linesAndNewlines.length - 1]) {
103246
+ linesAndNewlines.pop();
103247
+ }
103248
+ for (let i = 0; i < linesAndNewlines.length; i++) {
103249
+ const line = linesAndNewlines[i];
103250
+ if (i % 2 && !options.newlineIsToken) {
103251
+ retLines[retLines.length - 1] += line;
103252
+ } else {
103253
+ retLines.push(line);
103254
+ }
103255
+ }
103256
+ return retLines;
103257
+ }
103258
+
103259
+ // ../../packages/chat-core/src/turn-process/line-delta.ts
103260
+ function splitContentLines(text2) {
103261
+ if (!text2) return [];
103262
+ return text2.replace(/\r\n/g, "\n").replace(/\n$/, "").split("\n");
103263
+ }
103264
+ function countContentLines(text2) {
103265
+ return splitContentLines(text2).length;
103266
+ }
103267
+ function ensureTrailingNewline(s4) {
103268
+ if (!s4) return s4;
103269
+ return s4.endsWith("\n") ? s4 : s4 + "\n";
103270
+ }
103271
+ function countEditDelta2(oldStr, newStr) {
103272
+ let added = 0;
103273
+ let removed = 0;
103274
+ for (const change of diffLines2(ensureTrailingNewline(oldStr), ensureTrailingNewline(newStr))) {
103275
+ if (change.added) added += change.count ?? 0;
103276
+ else if (change.removed) removed += change.count ?? 0;
103277
+ }
103278
+ return { added, removed };
103279
+ }
103280
+ function countUnifiedDiffDelta(diff) {
103281
+ if (!diff) return null;
103282
+ const lines2 = diff.replace(/\r\n/g, "\n").split("\n");
103283
+ let inHunk = false;
103284
+ let added = 0;
103285
+ let removed = 0;
103286
+ for (const line of lines2) {
103287
+ if (line.startsWith("@@")) {
103288
+ inHunk = true;
103289
+ continue;
103290
+ }
103291
+ if (!inHunk || line.startsWith("\\")) continue;
103292
+ if (line.startsWith("+")) added++;
103293
+ else if (line.startsWith("-")) removed++;
103294
+ }
103295
+ return added > 0 || removed > 0 ? { added, removed } : null;
103296
+ }
103297
+ function countPrefixedDiffDelta(diff) {
103298
+ if (!diff) return null;
103299
+ const lines2 = diff.replace(/\r\n/g, "\n").split("\n");
103300
+ let added = 0;
103301
+ let removed = 0;
103302
+ for (const line of lines2) {
103303
+ if (line.startsWith("+") && !line.startsWith("+++")) added++;
103304
+ else if (line.startsWith("-") && !line.startsWith("---")) removed++;
103305
+ }
103306
+ return added > 0 || removed > 0 ? { added, removed } : null;
103307
+ }
103308
+ function countParamsDiffDelta(params) {
103309
+ const diff = String(params.diff ?? params.diffString ?? "");
103310
+ if (diff) {
103311
+ const counted = countUnifiedDiffDelta(diff) ?? countPrefixedDiffDelta(diff);
103312
+ if (counted) return counted;
103313
+ }
103314
+ const added = Number(params.linesAdded);
103315
+ const removed = Number(params.linesRemoved);
103316
+ const hasAdded = Number.isFinite(added) && added > 0;
103317
+ const hasRemoved = Number.isFinite(removed) && removed > 0;
103318
+ if (!hasAdded && !hasRemoved) return null;
103319
+ return { added: hasAdded ? added : 0, removed: hasRemoved ? removed : 0 };
103320
+ }
103321
+ function computeLineDelta(toolName, params) {
103322
+ if (toolName === "Write") {
103323
+ const content = String(params.content ?? "");
103324
+ if (!content) return null;
103325
+ const added = countContentLines(content);
103326
+ return { added, removed: 0 };
103327
+ }
103328
+ if (toolName === "Edit") {
103329
+ const oldStr = String(params.old_string ?? "");
103330
+ const newStr = String(params.new_string ?? "");
103331
+ if (oldStr || newStr) {
103332
+ const { added, removed } = countEditDelta2(oldStr, newStr);
103333
+ return added > 0 || removed > 0 ? { added, removed } : null;
103334
+ }
103335
+ return countParamsDiffDelta(params);
103336
+ }
103337
+ if (toolName === "Delete") return countParamsDiffDelta(params);
103338
+ if (toolName === "FileChange") {
103339
+ const kind = String(params.kind ?? "");
103340
+ const diff = String(params.diff ?? "");
103341
+ if (!diff) return null;
103342
+ if (kind === "add") return { added: countContentLines(diff), removed: 0 };
103343
+ if (kind === "delete") return { added: 0, removed: countContentLines(diff) };
103344
+ return countUnifiedDiffDelta(diff) ?? countPrefixedDiffDelta(diff);
103345
+ }
103346
+ return null;
103347
+ }
103348
+
103349
+ // ../../packages/chat-core/src/turn-process/process-stats.ts
103350
+ var EMPTY_TURN_PROCESS_STATS = {
103351
+ toolCalls: 0,
103352
+ filesChanged: 0,
103353
+ added: 0,
103354
+ removed: 0
103355
+ };
103356
+ function parseToolInput(input) {
103357
+ try {
103358
+ const parsed = JSON.parse(input);
103359
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
103360
+ } catch {
103361
+ return {};
103362
+ }
103363
+ }
103364
+ function* eachClaudeToolUse(seg) {
103365
+ if (seg.kind === "block" && seg.block?.type === "tool_use") {
103366
+ yield seg.block;
103367
+ return;
103368
+ }
103369
+ if (seg.kind === "tools" || seg.kind === "app-tools") {
103370
+ for (const block of seg.blocks ?? []) {
103371
+ if (block.type === "tool_use") yield block;
103372
+ }
103373
+ return;
103374
+ }
103375
+ if (seg.kind === "subagent" && seg.taskBlock) yield seg.taskBlock;
103376
+ if (seg.kind === "workflow" && seg.toolBlock) yield seg.toolBlock;
103377
+ }
103378
+ function* eachSubagentEdit(seg) {
103379
+ if (seg.kind !== "subagent") return;
103380
+ if (seg.childBlocks?.length) {
103381
+ for (const block of seg.childBlocks) {
103382
+ if (block.type === "tool_use") yield { block };
103383
+ }
103384
+ return;
103385
+ }
103386
+ for (const change of seg.taskBlock?.taskFileChanges ?? []) yield { change };
103387
+ }
103388
+ function lineDeltaForMutation(toolName, params) {
103389
+ if (toolName === "NotebookEdit") {
103390
+ return computeLineDelta("Edit", {
103391
+ old_string: String(params.old_source ?? ""),
103392
+ new_string: String(params.new_source ?? "")
103393
+ });
103394
+ }
103395
+ return computeLineDelta(toolName, params);
103396
+ }
103397
+ function accumulateMutation(stats, files, toolName, rawInput, projected) {
103398
+ if (isPatchToolCall(toolName, rawInput)) {
103399
+ const patchFiles = patchToolFiles(rawInput);
103400
+ for (const file2 of patchFiles) files.add(file2.movePath ?? file2.path);
103401
+ const summary2 = summarizePatchToolFiles(patchFiles);
103402
+ stats.added += summary2.added;
103403
+ stats.removed += summary2.removed;
103404
+ return;
103405
+ }
103406
+ const normalized = normalizeTranscriptTool(toolName, rawInput);
103407
+ if (!isFileMutationTool(normalized.toolName)) return;
103408
+ const path = fileMutationPath(normalized.input) || projected?.path || "";
103409
+ if (path) files.add(path);
103410
+ const delta = lineDeltaForMutation(normalized.toolName, normalized.input) ?? projected?.delta ?? null;
103411
+ if (!delta) return;
103412
+ stats.added += delta.added;
103413
+ stats.removed += delta.removed;
103414
+ }
103415
+ function summarizeClaudeProcessFiles(segs, opts) {
103416
+ const stats = { ...EMPTY_TURN_PROCESS_STATS };
103417
+ const files = /* @__PURE__ */ new Set();
103418
+ let moreFiles = 0;
103419
+ const failed2 = (toolUseId, result3) => opts.isErrorTool?.(toolUseId) === true || result3?.startsWith("[denied] ") === true;
103420
+ const accumulateChange = (change) => {
103421
+ if (change.path) files.add(change.path);
103422
+ stats.added += change.added;
103423
+ stats.removed += change.removed;
103424
+ };
103425
+ const accumulateBlock = (block) => {
103426
+ const bashEditDiff = block.toolName === "Bash" ? opts.bashEditDiffAt?.(block.toolUseId ?? "") : void 0;
103427
+ if (bashEditDiff) {
103428
+ for (const change of bashEditFileChanges(bashEditDiff)) accumulateChange(change);
103429
+ return;
103430
+ }
103431
+ accumulateMutation(stats, files, block.toolName ?? "", parseToolInput(block.input ?? ""), {
103432
+ path: block.toolFilePath,
103433
+ delta: block.toolLineDelta
103434
+ });
103435
+ };
103436
+ for (const seg of segs) {
103437
+ const fold = seg.kind === "block" ? seg.block?.fold : void 0;
103438
+ if (fold) {
103439
+ stats.toolCalls += fold.toolCalls;
103440
+ stats.added += fold.added;
103441
+ stats.removed += fold.removed;
103442
+ for (const path of fold.files) files.add(path);
103443
+ moreFiles += fold.moreFiles ?? 0;
103444
+ continue;
103445
+ }
103446
+ for (const block of eachClaudeToolUse(seg)) {
103447
+ const toolName = block.toolName ?? "";
103448
+ const toolUseId = block.toolUseId ?? "";
103449
+ const result3 = opts.toolResultAt(toolUseId);
103450
+ if (opts.isHiddenTool(toolName, result3)) continue;
103451
+ stats.toolCalls += 1;
103452
+ if (!failed2(toolUseId, result3)) accumulateBlock(block);
103453
+ }
103454
+ for (const edit of eachSubagentEdit(seg)) {
103455
+ if ("change" in edit) {
103456
+ accumulateChange(edit.change);
103457
+ continue;
103458
+ }
103459
+ const toolUseId = edit.block.toolUseId ?? "";
103460
+ if (!failed2(toolUseId, opts.toolResultAt(toolUseId))) accumulateBlock(edit.block);
103461
+ }
103462
+ }
103463
+ stats.filesChanged = files.size + moreFiles;
103464
+ return { stats, files, moreFiles };
103465
+ }
103466
+
103467
+ // ../../packages/chat-core/src/turn-process/process-folds.ts
103468
+ var MIN_FOLD_BLOCKS = 4;
103469
+ var NO_FOLDS = { ranges: [], summarize: () => ({ segments: 0, toolCalls: 0, files: [], added: 0, removed: 0, contentKey: "" }) };
103470
+ function planProcessFolds(message, context) {
103471
+ if (message.role !== "assistant" || message.status === "streaming") return NO_FOLDS;
103472
+ const cuts = (context?.cuts ?? []).filter((cut) => cut.metadata?.transcriptBoundary?.messageId === message.id);
103473
+ if (cuts.length > 0 && message.id && !isLegacyCodexMessage(message)) return planSliced(message, cuts);
103474
+ return planContent(message, message.content);
103475
+ }
103476
+ function planSliced(message, cuts) {
103477
+ const source = {
103478
+ id: message.id,
103479
+ role: "assistant",
103480
+ status: message.status === "error" ? "error" : "complete",
103481
+ createdAt: "",
103482
+ providerId: message.providerId ?? "claude",
103483
+ content: message.content,
103484
+ ...message.metadata ? { metadata: message.metadata } : {}
103485
+ };
103486
+ const grouped = groupTurn(turnDisplayContent(source));
103487
+ const opts = visibility(grouped);
103488
+ if (countVisibleClaudeProcessSegments(collapsibleItems(compactTurnRuns(grouped.segments, isPortablePinnedSegment)), opts) < MIN_PROCESS_SEGMENTS_TO_COLLAPSE) return NO_FOLDS;
103489
+ const indexOf = new Map(message.content.map((block, index) => [block, index]));
103490
+ const foldable = new Array(message.content.length);
103491
+ const anchored = /* @__PURE__ */ new Map();
103492
+ const calls2 = /* @__PURE__ */ new Set();
103493
+ const sliceEnds = /* @__PURE__ */ new Set();
103494
+ for (const row2 of transcriptView([source, ...cuts]).rows) {
103495
+ if (row2.source.id !== source.id) continue;
103496
+ let last = -1;
103497
+ for (const block of row2.message.content) {
103498
+ const index = indexOf.get(block);
103499
+ if (index !== void 0) last = Math.max(last, index);
103500
+ }
103501
+ if (last >= 0) sliceEnds.add(last);
103502
+ const slice = groupTurn(turnDisplayContent(row2.message));
103503
+ const following = row2.following ? groupTurn(turnDisplayContent(row2.following)) : void 0;
103504
+ const runs = compactTurnRuns(slice.segments, isPortablePinnedSegment, { source: grouped.segments, following: following?.segments });
103505
+ markFoldable(runs, (block) => indexOf.get(block), foldable, anchored, calls2);
103506
+ }
103507
+ for (const block of message.content) {
103508
+ const index = indexOf.get(block);
103509
+ if (index !== void 0 && isToolResultBlock(block) && calls2.has(block.toolUseId)) foldable[index] = block;
103510
+ }
103511
+ return finish(message.content, foldable, anchored, visibility(grouped), sliceEnds);
103512
+ }
103513
+ function planContent(message, content) {
103514
+ const indexes = [];
103515
+ const blocks = [];
103516
+ content.forEach((block, index) => {
103517
+ if (isOffTranscriptBlock(block, message)) return;
103518
+ indexes.push(index);
103519
+ blocks.push(portableToolBlock(block));
103520
+ });
103521
+ const grouped = groupContentPresenter(blocks, PORTABLE_GROUP_PORTS);
103522
+ const opts = visibility(grouped);
103523
+ const runs = compactTurnRuns(grouped.segments, isPortablePinnedSegment);
103524
+ if (countVisibleClaudeProcessSegments(collapsibleItems(runs), opts) < MIN_PROCESS_SEGMENTS_TO_COLLAPSE) return NO_FOLDS;
103525
+ const position2 = new Map(blocks.map((block, index) => [block, index]));
103526
+ const foldable = new Array(content.length);
103527
+ const anchored = /* @__PURE__ */ new Map();
103528
+ const calls2 = /* @__PURE__ */ new Set();
103529
+ markFoldable(runs, (block) => indexes[position2.get(block)], foldable, anchored, calls2);
103530
+ for (const block of blocks) {
103531
+ if (isToolResultBlock(block) && calls2.has(block.toolUseId)) foldable[indexes[position2.get(block)]] = block;
103532
+ }
103533
+ return finish(content, foldable, anchored, opts);
103534
+ }
103535
+ function groupTurn(content) {
103536
+ return groupContentPresenter(portableToolBlocks(content), PORTABLE_GROUP_PORTS);
103537
+ }
103538
+ function visibility(grouped) {
103539
+ return {
103540
+ toolResultAt: (id) => grouped.toolResultMap.get(id),
103541
+ isHiddenTool: isHiddenToolBlock,
103542
+ isErrorTool: (id) => grouped.errorToolIds.has(id),
103543
+ bashEditDiffAt: (id) => grouped.bashEditDiffMap.get(id)
103544
+ };
103545
+ }
103546
+ function markFoldable(runs, contentIndex, foldable, anchored, calls2) {
103547
+ for (const run of runs) {
103548
+ if (!run.collapsible) continue;
103549
+ for (const segment of run.items) {
103550
+ const members = segmentBlocks(segment);
103551
+ const first = members[0] ? contentIndex(members[0]) : void 0;
103552
+ if (first !== void 0) anchored.set(first, segment);
103553
+ for (const block of members) {
103554
+ const index = contentIndex(block);
103555
+ if (index === void 0) continue;
103556
+ if ("toolName" in block && isTurnGallerySourceTool(block.toolName)) continue;
103557
+ foldable[index] = block;
103558
+ if ("toolName" in block) calls2.add(block.toolUseId);
103559
+ }
103560
+ }
103561
+ }
103562
+ }
103563
+ function finish(content, foldable, anchored, opts, sliceEnds) {
103564
+ const keys = contentKeys(content);
103565
+ const summarize = (start, end) => {
103566
+ let segments = 0;
103567
+ const tools = [];
103568
+ for (let i = start; i <= end; i++) {
103569
+ const segment = anchored.get(i);
103570
+ if (segment && foldable[i] && isVisibleClaudeProcessSegment(segment, opts)) segments++;
103571
+ const block = foldable[i];
103572
+ if (block?.type === "tool_use") tools.push({ kind: "block", block, index: i });
103573
+ }
103574
+ const { stats, files, moreFiles } = summarizeClaudeProcessFiles(tools, opts);
103575
+ const listed = [...files].slice(0, MAX_FOLD_FILES);
103576
+ const more = files.size - listed.length + moreFiles;
103577
+ return {
103578
+ segments,
103579
+ toolCalls: stats.toolCalls,
103580
+ files: listed,
103581
+ ...more ? { moreFiles: more } : {},
103582
+ added: stats.added,
103583
+ removed: stats.removed,
103584
+ ...contentKeySpan(content, keys, start, end)
103585
+ };
103586
+ };
103587
+ const ranges = [];
103588
+ for (let start = 0; start < foldable.length; ) {
103589
+ if (!foldable[start]) {
103590
+ start++;
103591
+ continue;
103592
+ }
103593
+ let end = start;
103594
+ while (end + 1 < foldable.length && foldable[end + 1] && !sliceEnds?.has(end)) end++;
103595
+ if (end - start + 1 >= MIN_FOLD_BLOCKS) ranges.push({ start, end, summary: summarize(start, end) });
103596
+ start = end + 1;
103597
+ }
103598
+ return ranges.length ? { ranges, summarize } : NO_FOLDS;
103599
+ }
103600
+ function segmentBlocks(segment) {
103601
+ switch (segment.kind) {
103602
+ case "block":
103603
+ return [segment.block];
103604
+ case "subagent":
103605
+ return [segment.taskBlock, ...segment.childBlocks, ...segment.resultBlock ? [segment.resultBlock] : []];
103606
+ case "workflow":
103607
+ return [segment.toolBlock, ...segment.resultBlock ? [segment.resultBlock] : []];
103608
+ default:
103609
+ return segment.blocks;
103610
+ }
103611
+ }
103612
+
102086
103613
  // ../../packages/runtime/src/stream/delivery/window-projection.ts
102087
103614
  function projectWindowMessage(message) {
102088
- return stripMessagesForRemote([projectProgressiveMessage(message)], void 0, { splitText: false })[0];
103615
+ return stripMessagesForRemote([projectProgressiveMessage(revealTodoResults(message))], void 0, { splitText: false })[0];
102089
103616
  }
102090
103617
  var WINDOW_TEXT_DELTAS = /* @__PURE__ */ new Set(["text", "thinking", "plan", "review", "notice"]);
102091
103618
  var WINDOW_CONTENT_EVENTS = /* @__PURE__ */ new Set([
@@ -102141,34 +103668,80 @@ var LIVE_MESSAGE_BUDGET = { maxBytes: 64 * 1024, maxFragments: 24, targetChars:
102141
103668
  var LIVE_PATCH_BYTES = 256 * 1024;
102142
103669
  var MAX_HELD = 64;
102143
103670
  var SessionFragments = class {
103671
+ /** Times a message was fragmented and planned. A reparsed copy of the same content does not count. */
103672
+ plans = 0;
102144
103673
  fragmenter = new MessageFragmenter();
102145
103674
  cache = /* @__PURE__ */ new WeakMap();
102146
- of(message) {
102147
- let fragments = this.cache.get(message);
102148
- if (!fragments) {
102149
- fragments = this.fragmenter.fragment(projectWindowMessage(message));
102150
- this.cache.set(message, fragments);
102151
- }
102152
- return fragments;
103675
+ foldedCache = /* @__PURE__ */ new WeakMap();
103676
+ /** Last plan for a message id, so a newly parsed row does not plan the message again. */
103677
+ bySignature = /* @__PURE__ */ new Map();
103678
+ of(message, folds = false, cuts) {
103679
+ return folds ? this.folded(message, cuts).fragments : this.entry(message).fragments;
102153
103680
  }
102154
- source(transcript) {
103681
+ /**
103682
+ * The message with the process its settled turn collapses cut down to folds.
103683
+ * `cuts` are the other rows that split this turn. A later read of the same
103684
+ * content, parsed into a new object, reuses the plan; pass `cuts` only when
103685
+ * they may have changed.
103686
+ */
103687
+ folded(message, cuts) {
103688
+ const cutKey = foldCutKey(cuts);
103689
+ const cached5 = this.foldedCache.get(message);
103690
+ if (cached5 && (cuts === void 0 || cached5.cutKey === cutKey)) return cached5.view;
103691
+ const contentKey = foldContentKey(message);
103692
+ const stored = this.bySignature.get(message.id);
103693
+ if (stored && stored.contentKey === contentKey && (cuts === void 0 || stored.cutKey === cutKey)) {
103694
+ this.foldedCache.set(message, { cutKey: stored.cutKey, view: stored.view });
103695
+ return stored.view;
103696
+ }
103697
+ this.plans++;
103698
+ const { projected, fragments } = this.entry(message);
103699
+ const content = readableContent(projected);
103700
+ const planning = content === projected.content ? projected : { ...projected, content: [...content] };
103701
+ const plan = planProcessFolds(planning, cuts?.length ? { cuts } : void 0);
103702
+ const view = { fragments: foldMessageFragments(fragments, plan.ranges), plan };
103703
+ this.bySignature.set(message.id, { contentKey, cutKey, view });
103704
+ this.foldedCache.set(message, { cutKey, view });
103705
+ return view;
103706
+ }
103707
+ source(transcript, folds = false, cuts) {
102155
103708
  return {
102156
103709
  count: transcript.count,
102157
- at: (index) => this.of(transcript.messageAt(index)),
103710
+ at: (index) => {
103711
+ const message = transcript.messageAt(index);
103712
+ return this.of(message, folds, cuts?.get(message.id));
103713
+ },
102158
103714
  indexOf: (messageId) => transcript.indexOf(messageId)
102159
103715
  };
102160
103716
  }
103717
+ entry(message) {
103718
+ let entry3 = this.cache.get(message);
103719
+ if (!entry3) {
103720
+ const projected = projectWindowMessage(message);
103721
+ entry3 = { projected, fragments: this.fragmenter.fragment(projected) };
103722
+ this.cache.set(message, entry3);
103723
+ }
103724
+ return entry3;
103725
+ }
102161
103726
  retain(messages) {
102162
- this.fragmenter.retain(messages);
103727
+ const keep = new Set(messages);
103728
+ this.fragmenter.retain(keep);
103729
+ for (const id of this.bySignature.keys()) if (!keep.has(id)) this.bySignature.delete(id);
102163
103730
  }
102164
103731
  };
102165
103732
  var WindowViews = class {
102166
103733
  sessions = /* @__PURE__ */ new Map();
103734
+ /** Fold plans for a session this connection has not opened a window on yet. */
103735
+ spare = /* @__PURE__ */ new Map();
102167
103736
  /** Holders the 64-window cap dropped since the last drain. Switching a holder off a session is not an eviction. */
102168
103737
  evicted = [];
102169
103738
  has(sessionId) {
102170
103739
  return (this.sessions.get(sessionId)?.holders.size ?? 0) > 0;
102171
103740
  }
103741
+ /** How many times this connection fragmented a message to plan its folds. */
103742
+ plannedFolds(sessionId) {
103743
+ return this.fragmentsFor(sessionId).plans;
103744
+ }
102172
103745
  /** Holder ids following `sessionId`, oldest serve first. */
102173
103746
  holderIds(sessionId) {
102174
103747
  return [...this.sessions.get(sessionId)?.holders.keys() ?? []];
@@ -102180,14 +103753,16 @@ var WindowViews = class {
102180
103753
  serve(input) {
102181
103754
  const transcript = input.transcript ?? (input.messages ? arrayTranscript(input.messages) : null);
102182
103755
  if (!transcript) throw new Error("transcript window needs messages");
103756
+ const folds = input.request.folds === true;
102183
103757
  const session = this.session(input.sessionId);
102184
- const selected = selectTranscriptWindow(session.fragments.source(transcript), input.request, input.budget);
103758
+ const cuts = boundaryCuts(input.messages ?? transcript.boundaryMessages?.() ?? []);
103759
+ const selected = selectTranscriptWindow(session.fragments.source(transcript, folds, cuts), input.request, input.budget);
102185
103760
  const extend2 = input.request.anchor && input.request.direction !== "around" ? input.request.direction ?? "before" : null;
102186
103761
  const previous = session.holders.get(input.holder);
102187
- const held = extend2 && previous ? previous : { messages: /* @__PURE__ */ new Map(), order: [], atTail: false, total: 0, seen: /* @__PURE__ */ new Map() };
103762
+ const held = extend2 && previous?.folds === folds ? previous : { messages: /* @__PURE__ */ new Map(), order: [], atTail: false, total: 0, seen: /* @__PURE__ */ new Map(), folds };
102188
103763
  for (const message of selected.messages) {
102189
103764
  const source = transcript.messageAt(message.index);
102190
- const fragments = session.fragments.of(source);
103765
+ const fragments = session.fragments.of(source, folds, cuts.get(source.id));
102191
103766
  if (!held.messages.has(message.id)) held.seen.set(message.id, source);
102192
103767
  recordMessage(held, message, fragments, extend2 === "before" ? "before" : extend2 === "after" ? "after" : null);
102193
103768
  }
@@ -102211,9 +103786,10 @@ var WindowViews = class {
102211
103786
  patches(sessionId, messages) {
102212
103787
  const session = this.sessions.get(sessionId);
102213
103788
  if (!session) return [];
103789
+ const cuts = boundaryCuts(messages);
102214
103790
  const out = [];
102215
103791
  for (const [holder, held] of session.holders) {
102216
- const patch = diffHeld(held, messages, session.fragments);
103792
+ const patch = diffHeld(held, messages, session.fragments, cuts);
102217
103793
  if (patch) out.push({ holder, patch });
102218
103794
  }
102219
103795
  if (out.length) {
@@ -102222,6 +103798,30 @@ var WindowViews = class {
102222
103798
  }
102223
103799
  return out;
102224
103800
  }
103801
+ /**
103802
+ * The page behind fold `request.fold` of `message`, cut as this
103803
+ * connection's windows cut it. It changes no held window: the fold stays
103804
+ * one fragment there, and its pages live with the client.
103805
+ */
103806
+ fold(sessionId, message, request, budget) {
103807
+ const fragments = this.fragmentsFor(sessionId);
103808
+ const view = fragments.folded(message);
103809
+ if (!this.sessions.has(sessionId)) fragments.retain([message.id]);
103810
+ const inner = view.fragments.folds.get(request.fold);
103811
+ if (!inner) throw Object.assign(new Error("Fold no longer exists"), { code: "not_found" });
103812
+ if (foldRevision(inner.entries) !== request.revision) throw Object.assign(new Error("Fold changed"), { code: "failed_precondition" });
103813
+ const page2 = selectFoldPage(inner, request.after, budget);
103814
+ if (!page2) throw Object.assign(new Error("Fold page anchor no longer exists"), { code: "not_found" });
103815
+ const rest = page2.end < inner.entries.length ? { ...view.plan.summarize(inner.blocks[page2.end], inner.blocks[inner.blocks.length - 1]), fragments: inner.entries.length - page2.end } : null;
103816
+ return {
103817
+ sessionId,
103818
+ messageId: message.id,
103819
+ fold: request.fold,
103820
+ revision: request.revision,
103821
+ fragments: inner.entries.slice(page2.start, page2.end).map(({ key, digest, body }) => ({ key, digest, body })),
103822
+ rest
103823
+ };
103824
+ }
102225
103825
  close(sessionId, holder) {
102226
103826
  if (holder === void 0) {
102227
103827
  this.sessions.delete(sessionId);
@@ -102236,9 +103836,29 @@ var WindowViews = class {
102236
103836
  }
102237
103837
  session(sessionId) {
102238
103838
  let session = this.sessions.get(sessionId);
102239
- if (!session) this.sessions.set(sessionId, session = { fragments: new SessionFragments(), holders: /* @__PURE__ */ new Map() });
103839
+ if (!session) {
103840
+ const fragments = this.spare.get(sessionId) ?? new SessionFragments();
103841
+ this.spare.delete(sessionId);
103842
+ this.sessions.set(sessionId, session = { fragments, holders: /* @__PURE__ */ new Map() });
103843
+ }
102240
103844
  return session;
102241
103845
  }
103846
+ /** The fragmenter a window already holds, or the one fold pages keep warm. */
103847
+ fragmentsFor(sessionId) {
103848
+ const held = this.sessions.get(sessionId);
103849
+ if (held) return held.fragments;
103850
+ let fragments = this.spare.get(sessionId);
103851
+ if (!fragments) {
103852
+ fragments = new SessionFragments();
103853
+ this.spare.set(sessionId, fragments);
103854
+ while (this.spare.size > MAX_HELD) {
103855
+ const oldest = this.spare.keys().next().value;
103856
+ if (oldest === void 0) break;
103857
+ this.spare.delete(oldest);
103858
+ }
103859
+ }
103860
+ return fragments;
103861
+ }
102242
103862
  /** Most recently used sessions last, so eviction takes the stalest first. */
102243
103863
  touch(sessionId) {
102244
103864
  const session = this.sessions.get(sessionId);
@@ -102266,6 +103886,27 @@ var WindowViews = class {
102266
103886
  }
102267
103887
  }
102268
103888
  };
103889
+ function boundaryCuts(messages) {
103890
+ const cuts = /* @__PURE__ */ new Map();
103891
+ for (const message of messages) {
103892
+ const id = message.metadata?.transcriptBoundary?.messageId;
103893
+ if (!id || id === message.id) continue;
103894
+ const list = cuts.get(id);
103895
+ if (list) list.push(message);
103896
+ else cuts.set(id, [message]);
103897
+ }
103898
+ return cuts;
103899
+ }
103900
+ function foldContentKey(message) {
103901
+ return contentDigest(JSON.stringify([message.role, message.status, readableContent(message)]));
103902
+ }
103903
+ function foldCutKey(cuts) {
103904
+ if (!cuts?.length) return "";
103905
+ return cuts.map((cut) => {
103906
+ const boundary = cut.metadata?.transcriptBoundary;
103907
+ return `${cut.id}:${boundary?.order ?? ""}:${JSON.stringify(boundary?.content ?? {})}`;
103908
+ }).join("|");
103909
+ }
102269
103910
  function recordMessage(held, message, fragments, join54) {
102270
103911
  const previous = held.messages.get(message.id);
102271
103912
  const sent = message.fragments.map((fragment) => fragment.key);
@@ -102296,7 +103937,7 @@ function recordMessage(held, message, fragments, join54) {
102296
103937
  function heldFragment(digest, body) {
102297
103938
  return body.kind === "text" ? { digest, textLength: body.text.length } : { digest };
102298
103939
  }
102299
- function diffHeld(held, messages, fragments) {
103940
+ function diffHeld(held, messages, fragments, cuts) {
102300
103941
  const index = new Map(messages.map((message, i) => [message.id, i]));
102301
103942
  const present = held.order.filter((id) => index.has(id));
102302
103943
  const removed = held.order.filter((id) => !index.has(id));
@@ -102313,7 +103954,7 @@ function diffHeld(held, messages, fragments) {
102313
103954
  for (let r = range.length - 1; r >= 0; r--) {
102314
103955
  const source = messages[range[r]];
102315
103956
  if (held.seen.get(source.id) === source && held.messages.has(source.id)) continue;
102316
- const { message, record: record13 } = diffMessage(held.messages.get(source.id), fragments.of(source), range[r], Math.max(0, Math.min(LIVE_MESSAGE_BUDGET.maxBytes, remaining)));
103957
+ const { message, record: record13 } = diffMessage(held.messages.get(source.id), fragments.of(source, held.folds, cuts.get(source.id)), range[r], Math.max(0, Math.min(LIVE_MESSAGE_BUDGET.maxBytes, remaining)));
102317
103958
  const bytes = message ? patchBytes(message) : 0;
102318
103959
  if (bytes > remaining && changed.length) {
102319
103960
  start = r + 1;
@@ -106764,12 +108405,14 @@ init_transcript_window();
106764
108405
  var detailMessages = (sessions, sessionId) => sessions.detailMessages?.(sessionId) ?? sessions.messages(sessionId);
106765
108406
  function deliverLoad(result3, delivery) {
106766
108407
  if (!delivery) return result3;
106767
- if (summarizesTranscripts(delivery.policy) && !delivery.views.has(result3.sessionId)) delivery.views.open(result3.sessionId, true);
106768
- const messages = delivery.messages(result3.messages, result3.sessionId);
106769
- const activeTurn = result3.activeTurn && delivery.messages(result3.activeTurn, result3.sessionId);
108408
+ const summarize = summarizesTranscripts(delivery.policy);
108409
+ if (summarize && !delivery.views.has(result3.sessionId)) delivery.views.open(result3.sessionId, true);
108410
+ const deliverMessages = (messages2) => summarize ? delivery.messages(messages2, result3.sessionId) : messages2;
108411
+ const messages = deliverMessages(result3.messages);
108412
+ const activeTurn = result3.activeTurn && deliverMessages(result3.activeTurn);
106770
108413
  const restore = result3.restore && {
106771
108414
  ...result3.restore,
106772
- ...result3.restore.realtimeThreadMessages ? { realtimeThreadMessages: delivery.messages(result3.restore.realtimeThreadMessages, result3.sessionId) } : {}
108415
+ ...result3.restore.realtimeThreadMessages ? { realtimeThreadMessages: deliverMessages(result3.restore.realtimeThreadMessages) } : {}
106773
108416
  };
106774
108417
  const state = { ...result3.state };
106775
108418
  if (Array.isArray(state.queuedMessages)) {
@@ -106786,7 +108429,7 @@ function deliverLoad(result3, delivery) {
106786
108429
  ...restore ? { restore } : {},
106787
108430
  ...activeTurn ? { activeTurn } : {}
106788
108431
  };
106789
- return delivery.views.has(result3.sessionId) ? { ...delivered, summarized: true } : delivered;
108432
+ return summarize ? { ...delivered, summarized: true } : delivered;
106790
108433
  }
106791
108434
  function deliverFrame(frame, delivery, sessions) {
106792
108435
  const changed = /* @__PURE__ */ new Set();
@@ -106795,12 +108438,18 @@ function deliverFrame(frame, delivery, sessions) {
106795
108438
  const event = agentEventOf(envelope, sessions);
106796
108439
  if (!event) return [envelope];
106797
108440
  const sessionId = envelope.aggregateId;
106798
- const summarized = delivery.views.has(sessionId);
106799
- if (summarized) changed.add(sessionId);
106800
108441
  const holdsWindow = delivery.windows.has(sessionId);
106801
108442
  if (holdsWindow) windowed.set(sessionId, envelope);
108443
+ const desktopView = holdsWindow && desktopShowsSession(delivery.windows.holderIds(sessionId));
108444
+ if (!desktopView && delivery.views.has(sessionId) && !summarizesTranscripts(delivery.policy)) delivery.views.close(sessionId);
108445
+ else if (desktopView && !delivery.views.has(sessionId)) delivery.views.open(sessionId, true);
108446
+ const summarized = delivery.views.has(sessionId);
108447
+ if (summarized) changed.add(sessionId);
106802
108448
  const shaped = delivery.event(event, sessionId, summarized ? sessions.messages(sessionId) : []);
106803
- const live = holdsWindow && !desktopShowsSession(delivery.windows.holderIds(sessionId)) ? shaped.flatMap((next) => windowLiveEvent(next) ?? []) : shaped;
108449
+ const live = holdsWindow ? shaped.flatMap((next) => {
108450
+ const kept = windowLiveEvent(next);
108451
+ return kept ? [desktopView ? stripEventForRemote(kept) : kept] : [];
108452
+ }) : shaped;
106804
108453
  return live.map((next) => ({
106805
108454
  ...envelope,
106806
108455
  eventType: SESSION_DURABLE_EVENT.agentEvent,
@@ -106814,7 +108463,13 @@ function deliverFrame(frame, delivery, sessions) {
106814
108463
  }
106815
108464
  }
106816
108465
  const details = [...changed].flatMap((sessionId) => delivery.views.hasDetails(sessionId) ? delivery.details(sessionId, detailMessages(sessions, sessionId)).flatMap((event) => event.type === "remote_detail" ? [{ sessionId, update: { subscriptionId: event.subscriptionId, revision: event.revision, offset: event.offset, text: event.text } }] : []) : []);
106817
- const dropped = delivery.windows.drainEvicted().map((item) => item.sessionId);
108466
+ const evicted = delivery.windows.drainEvicted();
108467
+ if (!summarizesTranscripts(delivery.policy)) {
108468
+ for (const item of evicted) {
108469
+ if (!desktopShowsSession(delivery.windows.holderIds(item.sessionId))) delivery.views.close(item.sessionId);
108470
+ }
108471
+ }
108472
+ const dropped = evicted.map((item) => item.sessionId);
106818
108473
  const resnapshot = dropped.length ? [.../* @__PURE__ */ new Set([...frame.resnapshot ?? [], ...dropped])] : frame.resnapshot;
106819
108474
  return { frame: { ...frame, events: foldDeltas(events), ...resnapshot?.length ? { resnapshot } : {} }, details };
106820
108475
  }
@@ -106866,215 +108521,6 @@ function agentEventOf(envelope, sessions) {
106866
108521
  // ../../packages/shared/src/turn-outline.ts
106867
108522
  init_codex_async_question();
106868
108523
  init_transcript_markers();
106869
-
106870
- // ../../packages/shared/src/transcript-segments.ts
106871
- init_transcript_boundary();
106872
- init_content_delta();
106873
- init_codex_async_question();
106874
- init_codex_content();
106875
- var cachedSegments = /* @__PURE__ */ new WeakMap();
106876
- function sliceBlock(block, from, to2) {
106877
- if (from === 0 && to2 === blockText(block)?.length) return block;
106878
- if (block.type === "text") return to2 > from ? { ...block, text: block.text.slice(from, to2) } : null;
106879
- if (block.type === "thinking") return to2 > from || "remoteDetail" in block && block.remoteDetail ? { ...block, thinking: block.thinking.slice(from, to2) } : null;
106880
- return block;
106881
- }
106882
- function sliceItem(item, from, to2) {
106883
- if (from === 0 && to2 === itemText(item)?.length) return item;
106884
- if (!("text" in item)) return item;
106885
- if (to2 <= from && !(item.type === "agent_message" && item.questions?.length) && !(item.type === "reasoning" && item.remoteDetail)) return null;
106886
- return { ...item, text: item.text.slice(from, to2) };
106887
- }
106888
- function contentGroups(content) {
106889
- const groups = [[]];
106890
- const owners = /* @__PURE__ */ new Map();
106891
- for (const block of content) {
106892
- const parent = "parentToolUseId" in block ? block.parentToolUseId : null;
106893
- const owner = parent ? owners.get(parent) : isToolResultBlock(block) ? owners.get(block.toolUseId) : void 0;
106894
- if (owner) {
106895
- owner.push(block);
106896
- if (isToolUseBlock(block)) owners.set(block.toolUseId, owner);
106897
- continue;
106898
- }
106899
- if (block.type === "text" && !parent && groups.at(-1).length) groups.push([]);
106900
- const group = groups.at(-1);
106901
- group.push(block);
106902
- if (isToolUseBlock(block)) owners.set(block.toolUseId, group);
106903
- }
106904
- return groups;
106905
- }
106906
- function itemGroups(items) {
106907
- const groups = [[]];
106908
- for (const item of items) {
106909
- if (item.type === "agent_message" && item.delivery !== "async" && groups.at(-1).length) groups.push([]);
106910
- groups.at(-1).push(item);
106911
- }
106912
- return groups;
106913
- }
106914
- function interval(source, previous, next) {
106915
- const keys = contentKeys(source.content);
106916
- const parents = new Map(source.content.flatMap((block) => isToolUseBlock(block) && "parentToolUseId" in block && block.parentToolUseId ? [[block.toolUseId, block.parentToolUseId]] : []));
106917
- const rootOwner = (id) => {
106918
- const seen = /* @__PURE__ */ new Set();
106919
- while (parents.has(id) && !seen.has(id)) {
106920
- seen.add(id);
106921
- id = parents.get(id);
106922
- }
106923
- return `tool:${id}`;
106924
- };
106925
- const content = source.content.flatMap((block, index) => {
106926
- const key = keys[index];
106927
- const ownerKey = "parentToolUseId" in block && block.parentToolUseId ? rootOwner(block.parentToolUseId) : isToolResultBlock(block) ? rootOwner(block.toolUseId) : key;
106928
- const start = previous?.content[ownerKey];
106929
- const end = next?.content[ownerKey];
106930
- const text2 = blockText(block);
106931
- if (ownerKey !== key) return start !== void 0 || next && end === void 0 ? [] : [block];
106932
- if (text2 === void 0) return start !== void 0 || next && end === void 0 ? [] : [block];
106933
- if (next && end === void 0) return [];
106934
- if (start === -1) return [];
106935
- if (start !== void 0 && text2.length <= start) return [];
106936
- const value = sliceBlock(block, Math.max(0, start ?? 0), Math.min(text2.length, end ?? text2.length));
106937
- return value ? [value] : [];
106938
- });
106939
- const items = (source.metadata?.codex?.items ?? []).flatMap((item) => {
106940
- const start = previous?.items[item.id];
106941
- const end = next?.items[item.id];
106942
- const text2 = itemText(item);
106943
- if (text2 === void 0) return start !== void 0 || next && end === void 0 ? [] : [item];
106944
- if (next && end === void 0) return [];
106945
- if (start === -1) return [];
106946
- if (start !== void 0 && text2.length <= start) return [];
106947
- const value = sliceItem(item, Math.max(0, start ?? 0), Math.min(text2.length, end ?? text2.length));
106948
- return value ? [value] : [];
106949
- });
106950
- return { content, items };
106951
- }
106952
- function transcriptSegments(messages) {
106953
- return transcriptView(messages).segments;
106954
- }
106955
- function transcriptView(messages) {
106956
- const displayed = messages.filter((message) => !isDismissedCodexAsyncAnswer(message, messages));
106957
- const sources = new Set(displayed.map((message) => message.id));
106958
- const boundaries = /* @__PURE__ */ new Map();
106959
- const consumed = /* @__PURE__ */ new Set();
106960
- for (const message of displayed) {
106961
- const cursor = message.metadata?.transcriptBoundary;
106962
- if (!cursor || !sources.has(cursor.messageId) || cursor.messageId === message.id) continue;
106963
- const cutRows = boundaries.get(cursor.messageId) ?? [];
106964
- cutRows.push(message);
106965
- boundaries.set(cursor.messageId, cutRows);
106966
- consumed.add(message.id);
106967
- }
106968
- const result3 = [];
106969
- const rows = [];
106970
- for (const source of displayed) {
106971
- if (consumed.has(source.id)) continue;
106972
- if (source.role !== "assistant" || source.providerId === "system") {
106973
- const cursor = source.metadata?.transcriptBoundary;
106974
- result3.push({
106975
- id: source.id,
106976
- message: source,
106977
- source,
106978
- final: true,
106979
- anchorId: cursor?.messageId ?? source.id,
106980
- offset: cursor?.order ?? 0
106981
- });
106982
- rows.push({ id: source.id, message: source, source, final: true });
106983
- continue;
106984
- }
106985
- const cuts = (boundaries.get(source.id) ?? []).sort((a, b3) => a.metadata.transcriptBoundary.order - b3.metadata.transcriptBoundary.order);
106986
- const cached5 = cachedSegments.get(source);
106987
- if (cached5 && cached5.cuts.length === cuts.length && cached5.cuts.every((cut, index) => cut === cuts[index])) {
106988
- result3.push(...cached5.segments);
106989
- rows.push(...cached5.rows);
106990
- continue;
106991
- }
106992
- const cursors = cuts.length ? resolveTranscriptBoundaries(cuts, transcriptLengths(source)) : [];
106993
- const legacy = isLegacyCodexMessage(source);
106994
- const segmentOf = (message) => legacy ? withCodexContent(message) : message;
106995
- const finalResponse = (content) => content.filter((block) => block.type === "text" && block.id === void 0);
106996
- const sliceOf = (content, items) => segmentOf({
106997
- ...source,
106998
- status: "complete",
106999
- content,
107000
- metadata: { ...source.metadata, ...legacy ? { codex: { ...source.metadata.codex, items, finalResponse: void 0 } } : {} }
107001
- });
107002
- const keys = contentKeys(source.content);
107003
- const keyByBlock = new Map(source.content.map((block, index) => [block, keys[index]]));
107004
- const firstResult = result3.length;
107005
- const firstRow = rows.length;
107006
- let previous;
107007
- let firstTurnRow = true;
107008
- for (let part = 0; part <= cuts.length; part++) {
107009
- const next = cuts[part];
107010
- const slice = interval(source, cursors[part - 1], cursors[part]);
107011
- const groups = legacy ? itemGroups(slice.items).map((items, index, all) => ({
107012
- items,
107013
- content: index === all.length - 1 ? finalResponse(slice.content) : []
107014
- })) : contentGroups(slice.content).map((content) => ({ content, items: [] }));
107015
- const partSegments = [];
107016
- for (let group = 0; group < groups.length; group++) {
107017
- const value = groups[group];
107018
- if (!value.content.length && !value.items.length && next) continue;
107019
- const key = value.items[0]?.id ?? keyByBlock.get(value.content[0]) ?? `part-${part}`;
107020
- const id = result3.length === firstResult ? source.id : previous && group === 0 ? `${source.id}:after:${previous.id}` : `${source.id}:segment:${key}`;
107021
- const anchorId = source.id;
107022
- const offset = (previous ? previous.metadata.transcriptBoundary.order + 0.1 : 0) + group / (groups.length + 1) * 0.5;
107023
- const segment = { id, source, final: false, anchorId, offset, message: sliceOf(value.content, value.items) };
107024
- result3.push(segment);
107025
- partSegments.push({ segment, opens: { block: value.content[0], itemId: value.items[0]?.id } });
107026
- }
107027
- if (partSegments.length) {
107028
- const [first, ...rest] = partSegments;
107029
- const message = rest.length ? sliceOf(legacy ? finalResponse(slice.content) : slice.content, slice.items) : first.segment.message;
107030
- const anchors = /* @__PURE__ */ new Map();
107031
- for (const { segment, opens } of rest) {
107032
- const block = legacy ? message.content.find((candidate) => "id" in candidate && candidate.id === opens.itemId) : opens.block;
107033
- if (block) anchors.set(block, segment.id);
107034
- }
107035
- const following = next ? interval(source, cursors[part]) : void 0;
107036
- rows.push({
107037
- id: first.segment.id,
107038
- message,
107039
- source,
107040
- final: false,
107041
- first: firstTurnRow,
107042
- ...anchors.size ? { anchors } : {},
107043
- ...following ? { following: sliceOf(following.content, following.items) } : {}
107044
- });
107045
- firstTurnRow = false;
107046
- }
107047
- if (next) {
107048
- result3.push({
107049
- id: next.id,
107050
- message: next,
107051
- source: next,
107052
- final: true,
107053
- anchorId: source.id,
107054
- offset: next.metadata.transcriptBoundary.order
107055
- });
107056
- rows.push({ id: next.id, message: next, source: next, final: true });
107057
- }
107058
- previous = next;
107059
- }
107060
- const last = result3.findLast((segment) => segment.source === source);
107061
- const lastRow = rows.findLast((row2) => row2.source === source);
107062
- if (last) {
107063
- const shared = lastRow?.message === last.message;
107064
- last.final = true;
107065
- last.message = segmentOf({ ...last.message, status: source.status });
107066
- if (shared) lastRow.message = last.message;
107067
- }
107068
- if (lastRow) {
107069
- lastRow.final = true;
107070
- if (lastRow.message.status !== source.status) lastRow.message = segmentOf({ ...lastRow.message, status: source.status });
107071
- }
107072
- cachedSegments.set(source, { cuts, segments: result3.slice(firstResult), rows: rows.slice(firstRow) });
107073
- }
107074
- return { segments: result3, rows };
107075
- }
107076
-
107077
- // ../../packages/shared/src/turn-outline.ts
107078
108524
  function textOf2(message) {
107079
108525
  if (isCodexAsyncAnswer(message)) {
107080
108526
  const questions = codexAsyncAnswerQuestions(message, []);
@@ -107292,9 +108738,9 @@ async function handleSessionTranscriptWindow(payload, ctx) {
107292
108738
  if ("error" in target2) return target2;
107293
108739
  const parsed = parseWindowRequest(p3);
107294
108740
  if ("error" in parsed) return parsed;
107295
- const { anchor, direction, viewport, budget, have, holder } = parsed;
108741
+ const { anchor, direction, viewport, budget, have, holder, folds } = parsed;
107296
108742
  const includeState = parsed.includeState ?? !anchor;
107297
- const request = { anchor, direction, have };
108743
+ const request = { anchor, direction, have, folds };
107298
108744
  const limits = windowBudget({ budget, viewport });
107299
108745
  try {
107300
108746
  if (sessions.readTranscriptWindow) {
@@ -107324,6 +108770,8 @@ function windowResult(ctx, sessionId, holder, request, budget, view, includeStat
107324
108770
  request,
107325
108771
  budget
107326
108772
  });
108773
+ const desktopWindow = Boolean(delivery) && holder.startsWith(DESKTOP_WINDOW_HOLDER_PREFIX);
108774
+ if (desktopWindow) delivery?.views.open(sessionId, true);
107327
108775
  const shaped = deliverLoad({
107328
108776
  sessionId,
107329
108777
  state: view.state,
@@ -107341,22 +108789,38 @@ function windowResult(ctx, sessionId, holder, request, budget, view, includeStat
107341
108789
  total: selected.total,
107342
108790
  ...includeState ? { state: shaped.state, ...shaped.restore ? { restore: shaped.restore } : {} } : {},
107343
108791
  cursor: view.cursor,
107344
- ...shaped.summarized ? { summarized: true } : {}
108792
+ ...shaped.summarized || desktopWindow ? { summarized: true } : {}
107345
108793
  };
107346
108794
  return { result: result3 };
107347
108795
  }
107348
- function parseWindowRequest(p3) {
107349
- let anchor;
107350
- if (p3.anchor !== void 0) {
107351
- const a = asRecord(p3.anchor);
107352
- if (typeof a.messageId !== "string" || !a.messageId) return invalid5("anchor.messageId must be a non-empty string");
107353
- if (a.key !== void 0 && typeof a.key !== "string") return invalid5("anchor.key must be a string");
107354
- anchor = { messageId: a.messageId, ...typeof a.key === "string" ? { key: a.key } : {} };
107355
- }
107356
- if (p3.direction !== void 0 && p3.direction !== "before" && p3.direction !== "after" && p3.direction !== "around") {
107357
- return invalid5("direction must be before|after|around");
108796
+ async function handleSessionTranscriptFold(payload, ctx) {
108797
+ const denied = requireScopes(ctx.client, OPERATION_SCOPES.readSession);
108798
+ if (denied) return denied;
108799
+ const sessions = ctx.sessions;
108800
+ if (!sessions) return mapThrown(unsupportedMethodError(TRANSCRIPT_FOLD_METHOD));
108801
+ const p3 = asRecord(payload);
108802
+ const target2 = readSessionTarget(p3, sessions);
108803
+ if ("error" in target2) return target2;
108804
+ if (typeof p3.messageId !== "string" || !p3.messageId) return invalid5("messageId must be a non-empty string");
108805
+ if (typeof p3.fold !== "string" || !p3.fold) return invalid5("fold must be a non-empty string");
108806
+ if (typeof p3.revision !== "string" || !p3.revision) return invalid5("revision must be a non-empty string");
108807
+ if (p3.after !== void 0 && typeof p3.after !== "string") return invalid5("after must be a string");
108808
+ const limits = parseBudget(p3);
108809
+ if ("error" in limits) return limits;
108810
+ try {
108811
+ const message = sessions.detailMessage ? sessions.detailMessage(target2.sessionId, p3.messageId) : sessions.messages(target2.sessionId).find((candidate) => candidate.id === p3.messageId);
108812
+ if (!message) return { error: { code: "not_found", message: "History message no longer exists" } };
108813
+ const result3 = (ctx.streams?.delivery?.windows ?? new WindowViews()).fold(target2.sessionId, message, {
108814
+ fold: p3.fold,
108815
+ revision: p3.revision,
108816
+ ...typeof p3.after === "string" ? { after: p3.after } : {}
108817
+ }, windowBudget(limits));
108818
+ return { result: result3 };
108819
+ } catch (err) {
108820
+ return mapThrown(err);
107358
108821
  }
107359
- if (p3.direction !== void 0 && !anchor) return invalid5("direction requires an anchor");
108822
+ }
108823
+ function parseBudget(p3) {
107360
108824
  let viewport;
107361
108825
  if (p3.viewport !== void 0) {
107362
108826
  const v3 = asRecord(p3.viewport);
@@ -107371,16 +108835,33 @@ function parseWindowRequest(p3) {
107371
108835
  }
107372
108836
  budget = { maxBytes: b3.maxBytes, maxFragments: b3.maxFragments, targetChars: b3.targetChars };
107373
108837
  }
108838
+ return { ...viewport ? { viewport } : {}, ...budget ? { budget } : {} };
108839
+ }
108840
+ function parseWindowRequest(p3) {
108841
+ let anchor;
108842
+ if (p3.anchor !== void 0) {
108843
+ const a = asRecord(p3.anchor);
108844
+ if (typeof a.messageId !== "string" || !a.messageId) return invalid5("anchor.messageId must be a non-empty string");
108845
+ if (a.key !== void 0 && typeof a.key !== "string") return invalid5("anchor.key must be a string");
108846
+ anchor = { messageId: a.messageId, ...typeof a.key === "string" ? { key: a.key } : {} };
108847
+ }
108848
+ if (p3.direction !== void 0 && p3.direction !== "before" && p3.direction !== "after" && p3.direction !== "around") {
108849
+ return invalid5("direction must be before|after|around");
108850
+ }
108851
+ if (p3.direction !== void 0 && !anchor) return invalid5("direction requires an anchor");
108852
+ const limits = parseBudget(p3);
108853
+ if ("error" in limits) return limits;
107374
108854
  if (p3.have !== void 0 && !Array.isArray(p3.have)) return invalid5("have must be a list");
107375
108855
  if (p3.includeState !== void 0 && typeof p3.includeState !== "boolean") return invalid5("includeState must be boolean");
108856
+ if (p3.folds !== void 0 && typeof p3.folds !== "boolean") return invalid5("folds must be boolean");
107376
108857
  if (p3.holder !== void 0 && (typeof p3.holder !== "string" || p3.holder.length > MAX_HOLDER_LENGTH)) return invalid5("holder must be a short string");
107377
108858
  return {
107378
108859
  anchor,
107379
108860
  direction: p3.direction,
107380
- viewport,
107381
- budget,
108861
+ ...limits,
107382
108862
  have: p3.have,
107383
108863
  includeState: p3.includeState,
108864
+ folds: p3.folds === true,
107384
108865
  holder: typeof p3.holder === "string" ? p3.holder : ""
107385
108866
  };
107386
108867
  }
@@ -108445,6 +109926,7 @@ var HANDLERS = {
108445
109926
  "session.messages.list": (payload, ctx) => handleSessionMessagesList(payload, ctx),
108446
109927
  "session.load": (payload, ctx) => handleSessionLoad(payload, ctx),
108447
109928
  "session.transcriptWindow": (payload, ctx) => handleSessionTranscriptWindow(payload, ctx),
109929
+ "session.transcriptFold": (payload, ctx) => handleSessionTranscriptFold(payload, ctx),
108448
109930
  "session.historyIndex": (payload, ctx) => handleSessionHistoryIndex(payload, ctx),
108449
109931
  "session.subscribeDetail": (payload, ctx) => handleSessionSubscribeDetail(payload, ctx),
108450
109932
  "session.unsubscribeDetail": (payload, ctx) => handleSessionUnsubscribeDetail(payload, ctx),
@@ -116454,7 +117936,7 @@ var readBodyDirect = (request) => {
116454
117936
  const promise2 = new Promise((resolve22, reject) => {
116455
117937
  const chunks = [];
116456
117938
  let settled = false;
116457
- const finish = (callback) => {
117939
+ const finish2 = (callback) => {
116458
117940
  if (settled) return;
116459
117941
  settled = true;
116460
117942
  cleanup();
@@ -116463,7 +117945,7 @@ var readBodyDirect = (request) => {
116463
117945
  const recoverCompleteBodyAfterDisconnect = (error51) => {
116464
117946
  const streamError = incoming.errored ?? error51;
116465
117947
  if (!isRecoverableDisconnectedIncoming(incoming) || streamError && streamError.code !== "ECONNRESET") return false;
116466
- finish(() => {
117948
+ finish2(() => {
116467
117949
  const recovered = readBodyBufferedBeforeDisconnect(incoming, chunks);
116468
117950
  if (recovered instanceof Error) reject(recovered);
116469
117951
  else if (recovered === void 0) reject(error51 ?? normalizeAbortError(request, incoming));
@@ -116478,7 +117960,7 @@ var readBodyDirect = (request) => {
116478
117960
  chunks.push(toBufferChunk(chunk, incoming.readableEncoding));
116479
117961
  };
116480
117962
  const onEnd = () => {
116481
- finish(() => {
117963
+ finish2(() => {
116482
117964
  const buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks);
116483
117965
  request[bodyBufferKey] = buffer;
116484
117966
  resolve22(buffer);
@@ -116486,7 +117968,7 @@ var readBodyDirect = (request) => {
116486
117968
  };
116487
117969
  const onError = (error51) => {
116488
117970
  if (recoverCompleteBodyAfterDisconnect(error51)) return;
116489
- finish(() => {
117971
+ finish2(() => {
116490
117972
  reject(error51);
116491
117973
  });
116492
117974
  };
@@ -116496,7 +117978,7 @@ var readBodyDirect = (request) => {
116496
117978
  return;
116497
117979
  }
116498
117980
  if (recoverCompleteBodyAfterDisconnect()) return;
116499
- finish(() => {
117981
+ finish2(() => {
116500
117982
  reject(normalizeAbortError(request, incoming));
116501
117983
  });
116502
117984
  };