@geminixiang/mikan 1.0.1 → 1.1.0

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 (78) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/dist/adapters/discord/context.js +1 -1
  3. package/dist/adapters/discord/context.js.map +1 -1
  4. package/dist/adapters/messages.d.ts +1 -0
  5. package/dist/adapters/messages.d.ts.map +1 -1
  6. package/dist/adapters/messages.js +3 -0
  7. package/dist/adapters/messages.js.map +1 -1
  8. package/dist/adapters/progressive-renderer.d.ts.map +1 -1
  9. package/dist/adapters/progressive-renderer.js +132 -147
  10. package/dist/adapters/progressive-renderer.js.map +1 -1
  11. package/dist/adapters/slack/bot.d.ts +3 -0
  12. package/dist/adapters/slack/bot.d.ts.map +1 -1
  13. package/dist/adapters/slack/bot.js +88 -33
  14. package/dist/adapters/slack/bot.js.map +1 -1
  15. package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
  16. package/dist/adapters/slack/response-lifecycle.js +1 -3
  17. package/dist/adapters/slack/response-lifecycle.js.map +1 -1
  18. package/dist/adapters/telegram/context.js +1 -1
  19. package/dist/adapters/telegram/context.js.map +1 -1
  20. package/dist/adapters/types.d.ts +1 -2
  21. package/dist/adapters/types.d.ts.map +1 -1
  22. package/dist/adapters/types.js.map +1 -1
  23. package/dist/file-guards.d.ts +2 -0
  24. package/dist/file-guards.d.ts.map +1 -1
  25. package/dist/file-guards.js +2 -1
  26. package/dist/file-guards.js.map +1 -1
  27. package/dist/harness/execution-env.d.ts.map +1 -1
  28. package/dist/harness/execution-env.js +82 -5
  29. package/dist/harness/execution-env.js.map +1 -1
  30. package/dist/harness/presenter.d.ts.map +1 -1
  31. package/dist/harness/presenter.js +21 -28
  32. package/dist/harness/presenter.js.map +1 -1
  33. package/dist/harness/prompt.d.ts +3 -2
  34. package/dist/harness/prompt.d.ts.map +1 -1
  35. package/dist/harness/prompt.js +47 -6
  36. package/dist/harness/prompt.js.map +1 -1
  37. package/dist/harness/runner.d.ts.map +1 -1
  38. package/dist/harness/runner.js +5 -3
  39. package/dist/harness/runner.js.map +1 -1
  40. package/dist/harness/session.d.ts +2 -0
  41. package/dist/harness/session.d.ts.map +1 -1
  42. package/dist/harness/session.js +49 -8
  43. package/dist/harness/session.js.map +1 -1
  44. package/dist/harness/tools/task.d.ts +4 -0
  45. package/dist/harness/tools/task.d.ts.map +1 -1
  46. package/dist/harness/tools/task.js +12 -0
  47. package/dist/harness/tools/task.js.map +1 -1
  48. package/dist/harness/types.d.ts +7 -0
  49. package/dist/harness/types.d.ts.map +1 -1
  50. package/dist/harness/types.js.map +1 -1
  51. package/dist/runtime/conversation-runtime.d.ts.map +1 -1
  52. package/dist/runtime/conversation-runtime.js +15 -0
  53. package/dist/runtime/conversation-runtime.js.map +1 -1
  54. package/dist/runtime/session-lifecycle.d.ts +1 -0
  55. package/dist/runtime/session-lifecycle.d.ts.map +1 -1
  56. package/dist/runtime/session-lifecycle.js +17 -1
  57. package/dist/runtime/session-lifecycle.js.map +1 -1
  58. package/dist/runtime/types.d.ts +1 -0
  59. package/dist/runtime/types.d.ts.map +1 -1
  60. package/dist/runtime/types.js.map +1 -1
  61. package/dist/sandbox/container.d.ts +2 -1
  62. package/dist/sandbox/container.d.ts.map +1 -1
  63. package/dist/sandbox/container.js +23 -4
  64. package/dist/sandbox/container.js.map +1 -1
  65. package/dist/sandbox/provisioner.d.ts.map +1 -1
  66. package/dist/sandbox/provisioner.js +4 -0
  67. package/dist/sandbox/provisioner.js.map +1 -1
  68. package/dist/sessions/session-store.d.ts +4 -0
  69. package/dist/sessions/session-store.d.ts.map +1 -1
  70. package/dist/sessions/session-store.js +83 -4
  71. package/dist/sessions/session-store.js.map +1 -1
  72. package/dist/sessions/types.d.ts +1 -0
  73. package/dist/sessions/types.d.ts.map +1 -1
  74. package/dist/sessions/types.js.map +1 -1
  75. package/dist/types.d.ts +7 -6
  76. package/dist/types.d.ts.map +1 -1
  77. package/dist/types.js.map +1 -1
  78. package/package.json +7 -7
package/CHANGELOG.md CHANGED
@@ -11,6 +11,58 @@ change in a minor release.
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [1.1.0] - 2026-10-08
15
+
16
+ ### Added
17
+
18
+ - A DM task survives a restart. A deploy no longer waits up to five minutes for running
19
+ tasks, and a task interrupted by a deploy or crash in the last 24 hours resumes in its
20
+ thread with a notice. A stopped task stays stopped.
21
+ - A finished task's answer is written to the DM conversation that started it, so a later
22
+ question in the DM can be answered from the result.
23
+
24
+ ### Changed
25
+
26
+ - Pi packages are upgraded to 1.1.0. Retryable "server busy" provider errors are retried, the
27
+ first system prompt leads the model context so tool changes keep the prompt cache, and
28
+ each tool result records how long it ran. The container sandbox implements Pi's new file
29
+ reader in one `docker exec` per read, as before.
30
+ - Embedders: `ConversationResponder` no longer has `appendResponseDelta` or
31
+ `finishResponse`. `replaceResponse` always receives the whole main message, with
32
+ `{ final: true }` on the final write, and a responder sets `showsPartialAnswer` to receive
33
+ the answer while it is written. A responder that implemented the removed methods stops
34
+ receiving streamed text until it handles `replaceResponse` this way.
35
+
36
+ ### Fixed
37
+
38
+ - A task run is no longer offered `task_status` and `start_task`, which made one of three
39
+ test tasks report its own status instead of doing the work.
40
+ - A reply's message no longer flickers between its text and the tool checklist. Text written
41
+ before a tool call stays under the checklist until the next answer replaces it, the
42
+ message is updated at most once a second, and the final answer is written once instead of
43
+ three times. A Slack thread reply that has to change earlier text stops streaming and is
44
+ edited in place instead of deleted and posted again.
45
+ - The `...` that marks a reply still being written is removed when the reply ends, also when
46
+ the final edit is first rejected.
47
+ - A signature the model wrote at the end of its last line is replaced, so a reply no longer
48
+ ends with two `Triggered by` lines.
49
+ - A reply no longer streams with its first words missing. The first text of an answer, and
50
+ sometimes its last, never reached the chat while it streamed, so the message jumped when
51
+ the final version replaced it, and a Slack thread reply was deleted and posted again.
52
+
53
+ ## [1.0.2] - 2026-10-08
54
+
55
+ ### Changed
56
+
57
+ - The system prompt lists the folders already in the office's `scratch/` and asks the agent
58
+ to reuse an existing clone, with `git fetch` or `git worktree add`, before cloning again.
59
+ A new thread previously could not tell a repository was already there and cloned another copy.
60
+
61
+ ### Fixed
62
+
63
+ - A command left running in a container sandbox by a crashed or killed daemon is ended
64
+ when the daemon starts again, so a resumed or repeated run does not race the old copy.
65
+
14
66
  ## [1.0.1] - 2026-10-07
15
67
 
16
68
  ### Changed
@@ -47,7 +47,7 @@ export function createDiscordAdapters(event, bot) {
47
47
  formatContinuation: formatDiscordContinuation,
48
48
  errorPrefix: "*Error:* ",
49
49
  workingIndicator: " ...",
50
- supportsDeltas: true,
50
+ showsPartialAnswer: true,
51
51
  typing: {
52
52
  send: () => bot.sendTyping(channelId),
53
53
  intervalMs: 8000,
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/adapters/discord/context.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ConversationContext } from \"../../types.js\";\nimport { createConversationMessage } from \"../../office/index.js\";\nimport { resolveChatSessionKey } from \"../../sessions/session-key.js\";\nimport { createProgressiveRenderer, formatMarkdownToolResult } from \"../progressive-renderer.js\";\nimport { DISCORD_V2_TEXT_LIMIT } from \"./components.js\";\nimport { formatDiscordMarkdown } from \"./format.js\";\nimport type { DiscordEvent, DiscordResponseBot } from \"./types.js\";\n\nconst MAX_LENGTH = DISCORD_V2_TEXT_LIMIT - 100;\n\nconst formatDiscordContinuation = (partNum: number): string => `*(continued ${partNum})*`;\n\nfunction isDiscordMessageReference(id: string | undefined): id is string {\n return typeof id === \"string\" && id !== \"\" && !id.startsWith(\"event:\");\n}\n\nexport function createDiscordAdapters(\n event: DiscordEvent,\n bot: DiscordResponseBot,\n): ConversationContext {\n const conversationId = event.address.conversationId;\n const channelId = conversationId;\n const threadTargetId = isDiscordMessageReference(event.thread_ts) ? event.thread_ts : undefined;\n const replyTargetId = isDiscordMessageReference(event.ts) ? event.ts : undefined;\n\n const message = createConversationMessage({\n platform: \"discord\",\n conversationId,\n address: event.address,\n id: event.ts,\n sessionKey:\n event.sessionKey ??\n resolveChatSessionKey({\n conversationId,\n conversationKind: event.conversationKind,\n messageId: event.ts,\n persistentTopLevel: true,\n threadTs: event.thread_ts,\n }),\n conversationKind: event.conversationKind,\n userId: event.user,\n userName: event.userName,\n text: event.text,\n attachments: event.attachments,\n threadTs: event.thread_ts,\n });\n\n const platform = bot.getMessagingInfo();\n\n function postFirst(text: string): Promise<string> {\n if (threadTargetId) return bot.postInThread(channelId, threadTargetId, text);\n if (replyTargetId) return bot.postReply(channelId, replyTargetId, text);\n return bot.postMessage(channelId, text);\n }\n\n const { responder } = createProgressiveRenderer({\n label: \"Discord\",\n maxLength: MAX_LENGTH,\n formatContinuation: formatDiscordContinuation,\n errorPrefix: \"*Error:* \",\n workingIndicator: \" ...\",\n supportsDeltas: true,\n typing: {\n send: () => bot.sendTyping(channelId),\n intervalMs: 8000,\n stopOnSend: true,\n },\n prepareSource: (text) => formatDiscordMarkdown(text),\n formatToolResult: formatMarkdownToolResult,\n responseErrorContext: (responseId) => ({\n platform: \"discord\",\n conversationId,\n channelId,\n messageId: message.id,\n sessionKey: message.sessionKey,\n responseMessageId: responseId,\n threadTs: threadTargetId,\n replyTargetId,\n conversationKind: message.conversationKind,\n }),\n post: postFirst,\n update: (id, text) => bot.updateMessageRaw(channelId, id, text),\n postExtra: async (text, responseId) => {\n if (threadTargetId) return bot.postInThread(channelId, threadTargetId, text);\n if (replyTargetId) return bot.postReply(channelId, replyTargetId, text);\n if (responseId !== null) return bot.postReply(channelId, responseId, text);\n return bot.postMessage(channelId, text);\n },\n delete: (id) => bot.deleteMessageRaw(channelId, id),\n logBotResponse: (text, id) =>\n bot.logBotResponse(channelId, text, id, undefined, {\n answer: { replyTo: message.id, sessionKey: message.sessionKey },\n }),\n uploadFile: (filePath, title) => bot.uploadFile(channelId, filePath, title),\n react: replyTargetId ? (emoji) => bot.addReaction(channelId, replyTargetId, emoji) : undefined,\n });\n\n return { address: message.address, message, responder, platform };\n}\n"]}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/adapters/discord/context.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ConversationContext } from \"../../types.js\";\nimport { createConversationMessage } from \"../../office/index.js\";\nimport { resolveChatSessionKey } from \"../../sessions/session-key.js\";\nimport { createProgressiveRenderer, formatMarkdownToolResult } from \"../progressive-renderer.js\";\nimport { DISCORD_V2_TEXT_LIMIT } from \"./components.js\";\nimport { formatDiscordMarkdown } from \"./format.js\";\nimport type { DiscordEvent, DiscordResponseBot } from \"./types.js\";\n\nconst MAX_LENGTH = DISCORD_V2_TEXT_LIMIT - 100;\n\nconst formatDiscordContinuation = (partNum: number): string => `*(continued ${partNum})*`;\n\nfunction isDiscordMessageReference(id: string | undefined): id is string {\n return typeof id === \"string\" && id !== \"\" && !id.startsWith(\"event:\");\n}\n\nexport function createDiscordAdapters(\n event: DiscordEvent,\n bot: DiscordResponseBot,\n): ConversationContext {\n const conversationId = event.address.conversationId;\n const channelId = conversationId;\n const threadTargetId = isDiscordMessageReference(event.thread_ts) ? event.thread_ts : undefined;\n const replyTargetId = isDiscordMessageReference(event.ts) ? event.ts : undefined;\n\n const message = createConversationMessage({\n platform: \"discord\",\n conversationId,\n address: event.address,\n id: event.ts,\n sessionKey:\n event.sessionKey ??\n resolveChatSessionKey({\n conversationId,\n conversationKind: event.conversationKind,\n messageId: event.ts,\n persistentTopLevel: true,\n threadTs: event.thread_ts,\n }),\n conversationKind: event.conversationKind,\n userId: event.user,\n userName: event.userName,\n text: event.text,\n attachments: event.attachments,\n threadTs: event.thread_ts,\n });\n\n const platform = bot.getMessagingInfo();\n\n function postFirst(text: string): Promise<string> {\n if (threadTargetId) return bot.postInThread(channelId, threadTargetId, text);\n if (replyTargetId) return bot.postReply(channelId, replyTargetId, text);\n return bot.postMessage(channelId, text);\n }\n\n const { responder } = createProgressiveRenderer({\n label: \"Discord\",\n maxLength: MAX_LENGTH,\n formatContinuation: formatDiscordContinuation,\n errorPrefix: \"*Error:* \",\n workingIndicator: \" ...\",\n showsPartialAnswer: true,\n typing: {\n send: () => bot.sendTyping(channelId),\n intervalMs: 8000,\n stopOnSend: true,\n },\n prepareSource: (text) => formatDiscordMarkdown(text),\n formatToolResult: formatMarkdownToolResult,\n responseErrorContext: (responseId) => ({\n platform: \"discord\",\n conversationId,\n channelId,\n messageId: message.id,\n sessionKey: message.sessionKey,\n responseMessageId: responseId,\n threadTs: threadTargetId,\n replyTargetId,\n conversationKind: message.conversationKind,\n }),\n post: postFirst,\n update: (id, text) => bot.updateMessageRaw(channelId, id, text),\n postExtra: async (text, responseId) => {\n if (threadTargetId) return bot.postInThread(channelId, threadTargetId, text);\n if (replyTargetId) return bot.postReply(channelId, replyTargetId, text);\n if (responseId !== null) return bot.postReply(channelId, responseId, text);\n return bot.postMessage(channelId, text);\n },\n delete: (id) => bot.deleteMessageRaw(channelId, id),\n logBotResponse: (text, id) =>\n bot.logBotResponse(channelId, text, id, undefined, {\n answer: { replyTo: message.id, sessionKey: message.sessionKey },\n }),\n uploadFile: (filePath, title) => bot.uploadFile(channelId, filePath, title),\n react: replyTargetId ? (emoji) => bot.addReaction(channelId, replyTargetId, emoji) : undefined,\n });\n\n return { address: message.address, message, responder, platform };\n}\n"]}
@@ -5,6 +5,7 @@ export declare function formatNothingRunning(source: PlatformSource): string;
5
5
  export declare function formatStopping(source: PlatformSource): string;
6
6
  export declare function formatStopped(source: PlatformSource): string;
7
7
  export declare function formatRestarting(source: PlatformSource): string;
8
+ export declare function formatResumingTask(source: PlatformSource): string;
8
9
  export declare function formatAlreadyWorking(source: PlatformSource, stopCommand: string, options?: {
9
10
  scope?: "thread";
10
11
  }): string;
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/adapters/messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE/D,eAAO,MAAM,YAAY,UAAU,CAAC;AAEpC,KAAK,cAAc,GAAG,YAAY,GAAG,aAAa,GAAG,MAAM,CAAC;AAoB5D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAEnE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAE7D;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAE5D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAK/D;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,cAAc,EACtB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,QAAQ,CAAA;CAAE,GAC7B,MAAM,CAMR;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAErF"}
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/adapters/messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE/D,eAAO,MAAM,YAAY,UAAU,CAAC;AAEpC,KAAK,cAAc,GAAG,YAAY,GAAG,aAAa,GAAG,MAAM,CAAC;AAoB5D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAEnE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAE7D;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAE5D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAK/D;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAKjE;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,cAAc,EACtB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,QAAQ,CAAA;CAAE,GAC7B,MAAM,CAMR;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAErF"}
@@ -27,6 +27,9 @@ export function formatStopped(source) {
27
27
  export function formatRestarting(source) {
28
28
  return formatItalic(resolvePlatformName(source), "Restarting for an update; this reply was interrupted. Please send your message again.");
29
29
  }
30
+ export function formatResumingTask(source) {
31
+ return formatItalic(resolvePlatformName(source), "Restarted for an update; continuing this task.");
32
+ }
30
33
  export function formatAlreadyWorking(source, stopCommand, options) {
31
34
  const platformName = resolvePlatformName(source);
32
35
  const command = formatCode(platformName, stopCommand);
@@ -1 +1 @@
1
- {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/adapters/messages.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC;AAIpC,SAAS,mBAAmB,CAAC,MAAsB;IACjD,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC;IAC9C,IAAI,kBAAkB,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC,gBAAgB,EAAE,CAAC,IAAI,CAAC;IACxE,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED,SAAS,sBAAsB,CAAC,YAAoB;IAClD,OAAO,YAAY,KAAK,UAAU,CAAC;AACrC,CAAC;AAED,SAAS,YAAY,CAAC,YAAoB,EAAE,IAAY;IACtD,OAAO,sBAAsB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC;AACnE,CAAC;AAED,SAAS,UAAU,CAAC,YAAoB,EAAE,IAAY;IACpD,OAAO,sBAAsB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC;AACvF,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAsB;IACzD,OAAO,YAAY,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,kBAAkB,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAsB;IACnD,OAAO,YAAY,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAsB;IAClD,OAAO,YAAY,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAsB;IACrD,OAAO,YAAY,CACjB,mBAAmB,CAAC,MAAM,CAAC,EAC3B,uFAAuF,CACxF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,MAAsB,EACtB,WAAmB,EACnB,OAA8B;IAE9B,MAAM,YAAY,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,UAAU,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IACtD,MAAM,MAAM,GACV,OAAO,EAAE,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,kBAAkB,CAAC;IACvF,OAAO,YAAY,CAAC,YAAY,EAAE,GAAG,MAAM,SAAS,OAAO,aAAa,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAsB,EAAE,UAAkB;IAC3E,OAAO,YAAY,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,oBAAoB,UAAU,GAAG,CAAC,CAAC;AACtF,CAAC","sourcesContent":["import type { MessagingBot, MessagingInfo } from \"../types.js\";\n\nexport const PRODUCT_NAME = \"mikan\";\n\ntype PlatformSource = MessagingBot | MessagingInfo | string;\n\nfunction resolvePlatformName(source: PlatformSource): string {\n if (typeof source === \"string\") return source;\n if (\"getMessagingInfo\" in source) return source.getMessagingInfo().name;\n return source.name;\n}\n\nfunction supportsHtmlFormatting(platformName: string): boolean {\n return platformName === \"telegram\";\n}\n\nfunction formatItalic(platformName: string, text: string): string {\n return supportsHtmlFormatting(platformName) ? text : `_${text}_`;\n}\n\nfunction formatCode(platformName: string, text: string): string {\n return supportsHtmlFormatting(platformName) ? `<code>${text}</code>` : `\\`${text}\\``;\n}\n\nexport function formatNothingRunning(source: PlatformSource): string {\n return formatItalic(resolvePlatformName(source), \"Nothing running.\");\n}\n\nexport function formatStopping(source: PlatformSource): string {\n return formatItalic(resolvePlatformName(source), \"Stopping…\");\n}\n\nexport function formatStopped(source: PlatformSource): string {\n return formatItalic(resolvePlatformName(source), \"Stopped.\");\n}\n\nexport function formatRestarting(source: PlatformSource): string {\n return formatItalic(\n resolvePlatformName(source),\n \"Restarting for an update; this reply was interrupted. Please send your message again.\",\n );\n}\n\nexport function formatAlreadyWorking(\n source: PlatformSource,\n stopCommand: string,\n options?: { scope?: \"thread\" },\n): string {\n const platformName = resolvePlatformName(source);\n const command = formatCode(platformName, stopCommand);\n const prefix =\n options?.scope === \"thread\" ? \"Already working in this thread.\" : \"Already working.\";\n return formatItalic(platformName, `${prefix} Send ${command} to cancel.`);\n}\n\nexport function formatForceStopped(source: PlatformSource, actorLabel: string): string {\n return formatItalic(resolvePlatformName(source), `Force stopped by ${actorLabel}.`);\n}\n"]}
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/adapters/messages.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC;AAIpC,SAAS,mBAAmB,CAAC,MAAsB;IACjD,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC;IAC9C,IAAI,kBAAkB,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC,gBAAgB,EAAE,CAAC,IAAI,CAAC;IACxE,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED,SAAS,sBAAsB,CAAC,YAAoB;IAClD,OAAO,YAAY,KAAK,UAAU,CAAC;AACrC,CAAC;AAED,SAAS,YAAY,CAAC,YAAoB,EAAE,IAAY;IACtD,OAAO,sBAAsB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC;AACnE,CAAC;AAED,SAAS,UAAU,CAAC,YAAoB,EAAE,IAAY;IACpD,OAAO,sBAAsB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC;AACvF,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAsB;IACzD,OAAO,YAAY,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,kBAAkB,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAsB;IACnD,OAAO,YAAY,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAsB;IAClD,OAAO,YAAY,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAsB;IACrD,OAAO,YAAY,CACjB,mBAAmB,CAAC,MAAM,CAAC,EAC3B,uFAAuF,CACxF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAsB;IACvD,OAAO,YAAY,CACjB,mBAAmB,CAAC,MAAM,CAAC,EAC3B,gDAAgD,CACjD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,MAAsB,EACtB,WAAmB,EACnB,OAA8B;IAE9B,MAAM,YAAY,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,UAAU,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IACtD,MAAM,MAAM,GACV,OAAO,EAAE,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,kBAAkB,CAAC;IACvF,OAAO,YAAY,CAAC,YAAY,EAAE,GAAG,MAAM,SAAS,OAAO,aAAa,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAsB,EAAE,UAAkB;IAC3E,OAAO,YAAY,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,oBAAoB,UAAU,GAAG,CAAC,CAAC;AACtF,CAAC","sourcesContent":["import type { MessagingBot, MessagingInfo } from \"../types.js\";\n\nexport const PRODUCT_NAME = \"mikan\";\n\ntype PlatformSource = MessagingBot | MessagingInfo | string;\n\nfunction resolvePlatformName(source: PlatformSource): string {\n if (typeof source === \"string\") return source;\n if (\"getMessagingInfo\" in source) return source.getMessagingInfo().name;\n return source.name;\n}\n\nfunction supportsHtmlFormatting(platformName: string): boolean {\n return platformName === \"telegram\";\n}\n\nfunction formatItalic(platformName: string, text: string): string {\n return supportsHtmlFormatting(platformName) ? text : `_${text}_`;\n}\n\nfunction formatCode(platformName: string, text: string): string {\n return supportsHtmlFormatting(platformName) ? `<code>${text}</code>` : `\\`${text}\\``;\n}\n\nexport function formatNothingRunning(source: PlatformSource): string {\n return formatItalic(resolvePlatformName(source), \"Nothing running.\");\n}\n\nexport function formatStopping(source: PlatformSource): string {\n return formatItalic(resolvePlatformName(source), \"Stopping…\");\n}\n\nexport function formatStopped(source: PlatformSource): string {\n return formatItalic(resolvePlatformName(source), \"Stopped.\");\n}\n\nexport function formatRestarting(source: PlatformSource): string {\n return formatItalic(\n resolvePlatformName(source),\n \"Restarting for an update; this reply was interrupted. Please send your message again.\",\n );\n}\n\nexport function formatResumingTask(source: PlatformSource): string {\n return formatItalic(\n resolvePlatformName(source),\n \"Restarted for an update; continuing this task.\",\n );\n}\n\nexport function formatAlreadyWorking(\n source: PlatformSource,\n stopCommand: string,\n options?: { scope?: \"thread\" },\n): string {\n const platformName = resolvePlatformName(source);\n const command = formatCode(platformName, stopCommand);\n const prefix =\n options?.scope === \"thread\" ? \"Already working in this thread.\" : \"Already working.\";\n return formatItalic(platformName, `${prefix} Send ${command} to cancel.`);\n}\n\nexport function formatForceStopped(source: PlatformSource, actorLabel: string): string {\n return formatItalic(resolvePlatformName(source), `Force stopped by ${actorLabel}.`);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"progressive-renderer.d.ts","sourceRoot":"","sources":["../../src/adapters/progressive-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAA4B,MAAM,aAAa,CAAC;AAGnG,OAAO,KAAK,EAA8B,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAI1F,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CASvE;AAsgBD,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,2BAA2B,GAAG;IAChF,SAAS,EAAE,qBAAqB,CAAC;CAClC,CAEA"}
1
+ {"version":3,"file":"progressive-renderer.d.ts","sourceRoot":"","sources":["../../src/adapters/progressive-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EAGtB,MAAM,aAAa,CAAC;AAGrB,OAAO,KAAK,EAA8B,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAI1F,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CASvE;AAgeD,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,2BAA2B,GAAG;IAChF,SAAS,EAAE,qBAAqB,CAAC;CAClC,CAEA"}
@@ -27,13 +27,13 @@ class ProgressiveRenderer {
27
27
  streamActive: false,
28
28
  streamUnavailable: false,
29
29
  streamedSource: "",
30
- pendingChars: 0,
31
- lastFlushAt: 0,
32
- resetDelta: false,
33
30
  typingInterval: null,
34
31
  typingFailureWarned: false,
35
32
  extraIds: [],
36
33
  continuationIds: [],
34
+ shown: null,
35
+ lastWriteAt: 0,
36
+ flushTimer: null,
37
37
  };
38
38
  this.sanitize = platform.sanitize ?? ((text) => text);
39
39
  this.reportResponseError = platform.responseErrorContext
@@ -45,15 +45,10 @@ class ProgressiveRenderer {
45
45
  createResponder() {
46
46
  return {
47
47
  respond: (text) => this.respond(text),
48
- appendResponseDelta: this.platform.supportsDeltas || this.platform.stream
49
- ? (delta) => this.appendDelta(delta)
50
- : undefined,
51
- finishResponse: this.platform.supportsDeltas || this.platform.stream
52
- ? (finalText) => this.finishResponse(finalText)
53
- : undefined,
48
+ showsPartialAnswer: Boolean(this.platform.showsPartialAnswer || this.platform.stream),
54
49
  replaceResponse: (text, options) => this.replaceResponse(text, options),
55
50
  replaceSubagentProgress: this.platform.formatSubagentProgress
56
- ? (progress, finalText) => this.replaceSubagentProgress(progress, finalText)
51
+ ? (progress, finalText, options) => this.replaceSubagentProgress(progress, finalText, options)
57
52
  : undefined,
58
53
  respondDiagnostic: (text, options) => this.respondDiagnostic(text, options),
59
54
  respondToolResult: (result) => this.respondToolResult(result),
@@ -116,19 +111,6 @@ class ProgressiveRenderer {
116
111
  this.state.streamedSource = "";
117
112
  await this.platform.stream.stop(streamId);
118
113
  }
119
- async abandonNativeStream() {
120
- if (!this.platform.stream || this.state.responseId === null)
121
- return;
122
- const streamId = this.state.responseId;
123
- this.state.streamActive = false;
124
- this.state.streamedSource = "";
125
- await this.platform.stream.stop(streamId).catch(() => undefined);
126
- await this.platform.delete?.(streamId).catch((error) => {
127
- log.logWarning("Could not delete an abandoned stream message", errorMessage(error));
128
- });
129
- if (this.state.responseId === streamId)
130
- this.state.responseId = null;
131
- }
132
114
  async renderRaw(text, operation, options, canonicalText = text) {
133
115
  try {
134
116
  await this.postSplit(text);
@@ -150,77 +132,37 @@ class ProgressiveRenderer {
150
132
  return fallback.text;
151
133
  }
152
134
  }
153
- async renderDelta(text) {
154
- if (this.state.working && !text.trim())
155
- return text;
156
- const prepared = this.platform.prepareSource?.(text, this.state.working) ?? text;
157
- const stream = this.platform.stream;
158
- const display = this.provisional(prepared, this.state.working);
159
- if (!stream || this.state.streamUnavailable) {
160
- await this.renderRaw(display, "render", undefined, prepared);
161
- return prepared;
162
- }
163
- if (this.state.responseId !== null && !this.state.streamActive) {
164
- await this.renderRaw(display, "render", undefined, prepared);
165
- return prepared;
166
- }
167
- if (this.state.responseId !== null &&
168
- this.state.streamActive &&
169
- !prepared.startsWith(this.state.streamedSource)) {
170
- await this.abandonNativeStream();
171
- await this.renderRaw(display, "render", undefined, prepared);
172
- return prepared;
173
- }
174
- try {
175
- if (this.state.responseId !== null) {
176
- const delta = prepared.slice(this.state.streamedSource.length);
177
- if (delta && delta.length >= (stream.minDeltaChars ?? 0)) {
178
- await stream.append(this.state.responseId, delta);
179
- this.state.streamedSource = prepared;
180
- }
181
- return prepared;
182
- }
183
- this.state.responseId = await stream.start(prepared);
184
- this.state.streamActive = true;
185
- this.state.streamedSource = prepared;
186
- return prepared;
187
- }
188
- catch (err) {
189
- this.state.streamUnavailable = true;
190
- log.logWarning("Native response streaming unavailable; falling back to message updates", errorMessage(err));
191
- await this.abandonNativeStream();
192
- await this.renderRaw(display, "render", undefined, prepared);
193
- return prepared;
194
- }
195
- }
196
- async renderFinal(text) {
135
+ async renderFinal(text, options) {
197
136
  const stream = this.platform.stream;
198
137
  if (stream && this.state.streamActive && this.state.responseId !== null) {
199
- let streamed = false;
138
+ const streamId = this.state.responseId;
139
+ const extendsStream = text.startsWith(this.state.streamedSource);
140
+ this.state.streamActive = false;
200
141
  try {
201
- if (text.startsWith(this.state.streamedSource)) {
142
+ if (extendsStream) {
202
143
  const delta = text.slice(this.state.streamedSource.length);
203
144
  if (delta)
204
- await stream.append(this.state.responseId, delta);
205
- await stream.stop(this.state.responseId);
206
- streamed = true;
145
+ await stream.append(streamId, delta);
207
146
  }
147
+ await stream.stop(streamId);
208
148
  }
209
149
  catch (err) {
210
150
  this.state.streamUnavailable = true;
211
151
  log.logWarning("Native response streaming unavailable; falling back to message updates", errorMessage(err));
152
+ await stream.stop(streamId).catch(() => undefined);
153
+ return this.renderRaw(text, "replace", options);
212
154
  }
213
- this.state.streamActive = false;
214
- this.state.streamedSource = "";
215
- if (streamed) {
216
- if (this.platform.needsCanonicalRender?.(text))
217
- await this.renderRaw(text, "render");
218
- return text;
155
+ finally {
156
+ this.state.streamedSource = "";
219
157
  }
220
- await this.abandonNativeStream();
158
+ if (extendsStream && !this.platform.needsCanonicalRender?.(text))
159
+ return text;
160
+ return this.renderRaw(text, "replace", options);
221
161
  }
162
+ if (text === this.state.shown)
163
+ return text;
222
164
  if (this.state.responseId !== null || text)
223
- return this.renderRaw(text, "render");
165
+ return this.renderRaw(text, "replace", options);
224
166
  return text;
225
167
  }
226
168
  async run(label, operation, work, extra) {
@@ -235,43 +177,18 @@ class ProgressiveRenderer {
235
177
  }
236
178
  catch { }
237
179
  }
238
- if (label === "replaceResponse" || label === "finishResponse")
180
+ if (label === "finalResponse")
239
181
  throw err;
240
182
  });
241
183
  this.queueTail = handled.catch(() => undefined);
242
184
  return handled;
243
185
  }
244
- async appendDelta(delta) {
245
- await this.run("appendResponseDelta", "respond", async () => {
246
- if (!delta)
247
- return;
248
- if (this.state.resetDelta) {
249
- this.state.source = "";
250
- this.state.pendingChars = 0;
251
- this.state.resetDelta = false;
252
- }
253
- const sanitized = this.sanitize(delta);
254
- this.state.source += sanitized;
255
- this.state.pendingChars += sanitized.length;
256
- const elapsed = this.now() - this.state.lastFlushAt;
257
- if (this.state.lastFlushAt === 0 ||
258
- (elapsed >= this.flushIntervalMs && this.state.pendingChars > 0)) {
259
- this.state.pendingChars = 0;
260
- try {
261
- this.state.source = await this.renderDelta(this.state.source);
262
- }
263
- finally {
264
- this.state.lastFlushAt = this.now();
265
- }
266
- }
267
- }, () => ({ textLength: delta.length, accumulatedLength: this.state.source.length }));
268
- }
269
186
  async respond(text) {
270
187
  await this.run("respond", "respond", async () => {
271
188
  const sanitized = this.sanitize(text);
272
189
  this.state.source = this.state.source ? `${this.state.source}\n${sanitized}` : sanitized;
273
- this.state.pendingChars = 0;
274
- this.state.source = await this.renderDelta(this.state.source);
190
+ this.cancelFlush();
191
+ await this.renderView();
275
192
  if (this.state.responseId !== null && this.platform.logIntermediateResponses) {
276
193
  this.platform.logBotResponse?.(text, this.state.responseId);
277
194
  }
@@ -281,37 +198,109 @@ class ProgressiveRenderer {
281
198
  accumulatedLength: this.state.source.length,
282
199
  }));
283
200
  }
284
- async finishResponse(finalText) {
285
- await this.run("finishResponse", "set_working", async () => {
286
- if (finalText !== undefined)
287
- this.state.source = this.sanitize(finalText);
288
- this.state.resetDelta = false;
289
- this.state.pendingChars = 0;
290
- this.stopTyping();
291
- this.state.working = false;
292
- this.state.source = await this.renderFinal(this.state.source);
293
- if (this.state.responseId !== null) {
294
- this.platform.logBotResponse?.(this.state.source, this.state.responseId);
295
- }
296
- await this.platform.onFinish?.(this.state.source, this.state.responseId);
297
- }, () => ({ finalTextLength: finalText?.length }));
298
- }
299
201
  async replaceResponse(text, options) {
300
- await this.run("replaceResponse", "replace_response", async () => {
202
+ await this.run(options?.final ? "finalResponse" : "replaceResponse", "replace_response", async () => {
301
203
  this.state.source = this.sanitize(text);
302
- this.state.pendingChars = 0;
303
- this.state.resetDelta = true;
204
+ if (options?.final)
205
+ await this.finish(options);
206
+ else
207
+ await this.show(options);
208
+ }, () => ({
209
+ textLength: text.length,
210
+ hadExistingResponse: Boolean(this.state.responseId),
211
+ final: options?.final === true,
212
+ }));
213
+ }
214
+ async show(options) {
215
+ if (this.state.working && !this.state.source.trim())
216
+ return;
217
+ const wait = this.state.lastWriteAt + this.flushIntervalMs - this.now();
218
+ if (this.state.working && wait > 0) {
219
+ this.scheduleFlush(wait);
220
+ return;
221
+ }
222
+ await this.renderView(options);
223
+ }
224
+ async finish(options) {
225
+ this.stopTyping();
226
+ this.cancelFlush();
227
+ this.state.working = false;
228
+ this.state.source = await this.renderFinal(this.state.source, options);
229
+ this.state.shown = this.state.source;
230
+ this.state.lastWriteAt = this.now();
231
+ if (this.state.responseId !== null) {
232
+ this.platform.logBotResponse?.(this.state.source, this.state.responseId);
233
+ }
234
+ await this.platform.onFinish?.(this.state.source, this.state.responseId);
235
+ }
236
+ scheduleFlush(delayMs) {
237
+ if (this.state.flushTimer !== null)
238
+ return;
239
+ this.state.flushTimer = setTimeout(() => {
240
+ this.state.flushTimer = null;
241
+ void this.run("flushResponse", "replace_response", () => this.renderView(), () => ({ deferred: true }));
242
+ }, delayMs);
243
+ this.state.flushTimer.unref?.();
244
+ }
245
+ cancelFlush() {
246
+ if (this.state.flushTimer === null)
247
+ return;
248
+ clearTimeout(this.state.flushTimer);
249
+ this.state.flushTimer = null;
250
+ }
251
+ async renderView(options) {
252
+ if (this.state.working && !this.state.source.trim())
253
+ return;
254
+ const prepared = this.platform.prepareSource?.(this.state.source, this.state.working) ?? this.state.source;
255
+ const display = this.provisional(prepared, this.state.working);
256
+ if (display === this.state.shown)
257
+ return;
258
+ try {
259
+ await this.writeView(prepared, display, options);
260
+ }
261
+ finally {
262
+ this.state.lastWriteAt = this.now();
263
+ }
264
+ this.state.shown = display;
265
+ }
266
+ async writeView(prepared, display, options) {
267
+ const stream = this.platform.stream;
268
+ const canStream = stream !== undefined &&
269
+ this.state.working &&
270
+ !this.state.streamUnavailable &&
271
+ (this.state.responseId === null ||
272
+ (this.state.streamActive && prepared.startsWith(this.state.streamedSource)));
273
+ try {
274
+ if (canStream && this.state.responseId === null) {
275
+ this.state.responseId = await stream.start(prepared);
276
+ this.state.streamActive = true;
277
+ this.state.streamedSource = prepared;
278
+ }
279
+ else if (canStream && this.state.responseId !== null) {
280
+ const delta = prepared.slice(this.state.streamedSource.length);
281
+ if (delta)
282
+ await stream.append(this.state.responseId, delta);
283
+ this.state.streamedSource = prepared;
284
+ }
285
+ else {
286
+ if (this.state.streamActive)
287
+ await this.stopNativeStream();
288
+ await this.renderRaw(display, "render", options, prepared);
289
+ }
290
+ }
291
+ catch (err) {
292
+ if (!canStream)
293
+ throw err;
294
+ this.state.streamUnavailable = true;
295
+ log.logWarning("Native response streaming unavailable; falling back to message updates", errorMessage(err));
304
296
  if (this.state.streamActive)
305
- await this.stopNativeStream();
306
- if (this.state.working && !this.state.source.trim())
307
- return;
308
- const prepared = this.platform.prepareSource?.(this.state.source, this.state.working) ?? this.state.source;
309
- this.state.source = await this.renderRaw(this.provisional(prepared, this.state.working), "replace", options, prepared);
310
- }, () => ({ textLength: text.length, hadExistingResponse: Boolean(this.state.responseId) }));
297
+ await this.stopNativeStream().catch(() => undefined);
298
+ await this.renderRaw(display, "render", options, prepared);
299
+ }
311
300
  }
312
- async replaceSubagentProgress(progress, finalText) {
301
+ async replaceSubagentProgress(progress, finalText, options) {
313
302
  const dashboard = this.platform.formatSubagentProgress(progress);
314
- await this.responder.replaceResponse(finalText ? `${dashboard}\n\n${finalText}` : dashboard);
303
+ await this.responder.replaceResponse(finalText ? `${dashboard}\n\n${finalText}` : dashboard, options);
315
304
  }
316
305
  async respondDiagnostic(text, options = {}) {
317
306
  await this.run("respondDiagnostic", "respond_diagnostic", async () => {
@@ -353,22 +342,16 @@ class ProgressiveRenderer {
353
342
  async setWorking(working) {
354
343
  await this.run("setWorking", "set_working", async () => {
355
344
  this.state.working = working;
356
- if (!working)
345
+ if (!working) {
357
346
  this.stopTyping();
358
- await this.platform.onWorkingChanged?.(working, this.state.responseId);
359
- if (this.state.responseId === null ||
360
- (!this.platform.workingIndicator && !this.platform.stream)) {
361
- return;
347
+ this.cancelFlush();
362
348
  }
363
- if (working && !this.state.source.trim())
349
+ await this.platform.onWorkingChanged?.(working, this.state.responseId);
350
+ if (this.state.responseId === null)
364
351
  return;
365
- if (this.state.streamActive && !working) {
352
+ if (!working && this.state.streamActive)
366
353
  await this.stopNativeStream();
367
- return;
368
- }
369
- if (this.state.responseId !== null) {
370
- this.state.source = await this.renderRaw(this.provisional(this.state.source, working), "render", undefined, this.state.source);
371
- }
354
+ await this.renderView();
372
355
  }, () => ({ working }));
373
356
  }
374
357
  async uploadFile(filePath, title) {
@@ -384,6 +367,8 @@ class ProgressiveRenderer {
384
367
  async deleteResponse() {
385
368
  await this.run("deleteResponse", "respond", async () => {
386
369
  this.stopTyping();
370
+ this.cancelFlush();
371
+ this.state.shown = null;
387
372
  if (this.state.streamActive)
388
373
  await this.stopNativeStream().catch(() => undefined);
389
374
  for (const id of [...this.state.extraIds, ...this.state.continuationIds]) {
@@ -405,7 +390,7 @@ class ProgressiveRenderer {
405
390
  this.state.streamUnavailable = false;
406
391
  this.state.streamedSource = "";
407
392
  this.state.streamActive = false;
408
- this.state.resetDelta = false;
393
+ this.state.lastWriteAt = 0;
409
394
  this.state.working = true;
410
395
  }, () => ({}));
411
396
  }