@sumicom/quicksave 0.8.6 → 0.8.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +1 -1
  3. package/dist/ai/asyncQueue.d.ts.map +1 -1
  4. package/dist/ai/asyncQueue.js +2 -0
  5. package/dist/ai/asyncQueue.js.map +1 -1
  6. package/dist/ai/attachmentStaging.d.ts +71 -0
  7. package/dist/ai/attachmentStaging.d.ts.map +1 -0
  8. package/dist/ai/attachmentStaging.js +243 -0
  9. package/dist/ai/attachmentStaging.js.map +1 -0
  10. package/dist/ai/attachmentStore.d.ts +40 -0
  11. package/dist/ai/attachmentStore.d.ts.map +1 -0
  12. package/dist/ai/attachmentStore.js +173 -0
  13. package/dist/ai/attachmentStore.js.map +1 -0
  14. package/dist/ai/cardBuilder.d.ts +3 -2
  15. package/dist/ai/cardBuilder.d.ts.map +1 -1
  16. package/dist/ai/cardBuilder.js +156 -5
  17. package/dist/ai/cardBuilder.js.map +1 -1
  18. package/dist/ai/claudeCliProvider.d.ts +7 -2
  19. package/dist/ai/claudeCliProvider.d.ts.map +1 -1
  20. package/dist/ai/claudeCliProvider.js +29 -11
  21. package/dist/ai/claudeCliProvider.js.map +1 -1
  22. package/dist/ai/claudeCodeProvider.d.ts.map +1 -1
  23. package/dist/ai/claudeCodeProvider.js +2 -0
  24. package/dist/ai/claudeCodeProvider.js.map +1 -1
  25. package/dist/ai/claudeSdkProvider.d.ts +2 -1
  26. package/dist/ai/claudeSdkProvider.d.ts.map +1 -1
  27. package/dist/ai/claudeSdkProvider.js +76 -12
  28. package/dist/ai/claudeSdkProvider.js.map +1 -1
  29. package/dist/ai/codexAppServer/approvalMapping.d.ts.map +1 -1
  30. package/dist/ai/codexAppServer/approvalMapping.js.map +1 -1
  31. package/dist/ai/codexAppServer/cardAdapter.d.ts.map +1 -1
  32. package/dist/ai/codexAppServer/cardAdapter.js.map +1 -1
  33. package/dist/ai/codexAppServer/index.d.ts.map +1 -1
  34. package/dist/ai/codexAppServer/index.js +2 -0
  35. package/dist/ai/codexAppServer/index.js.map +1 -1
  36. package/dist/ai/codexAppServer/overrideStore.d.ts.map +1 -1
  37. package/dist/ai/codexAppServer/overrideStore.js.map +1 -1
  38. package/dist/ai/codexAppServer/permissionMapping.d.ts.map +1 -1
  39. package/dist/ai/codexAppServer/permissionMapping.js.map +1 -1
  40. package/dist/ai/codexAppServer/processManager.d.ts.map +1 -1
  41. package/dist/ai/codexAppServer/processManager.js +2 -0
  42. package/dist/ai/codexAppServer/processManager.js.map +1 -1
  43. package/dist/ai/codexAppServer/provider.d.ts.map +1 -1
  44. package/dist/ai/codexAppServer/provider.js +1 -1
  45. package/dist/ai/codexAppServer/provider.js.map +1 -1
  46. package/dist/ai/codexAppServer/rpcClient.d.ts.map +1 -1
  47. package/dist/ai/codexAppServer/rpcClient.js.map +1 -1
  48. package/dist/ai/codexAppServer/schema/index.d.ts.map +1 -1
  49. package/dist/ai/codexAppServer/schema/index.js +2 -0
  50. package/dist/ai/codexAppServer/schema/index.js.map +1 -1
  51. package/dist/ai/codexAppServer/stdioTransport.d.ts.map +1 -1
  52. package/dist/ai/codexAppServer/stdioTransport.js.map +1 -1
  53. package/dist/ai/codexAppServer/tokenAccounting.d.ts.map +1 -1
  54. package/dist/ai/codexAppServer/tokenAccounting.js.map +1 -1
  55. package/dist/ai/codexAppServer/version.d.ts.map +1 -1
  56. package/dist/ai/codexAppServer/version.js +2 -0
  57. package/dist/ai/codexAppServer/version.js.map +1 -1
  58. package/dist/ai/codexLogin.d.ts.map +1 -1
  59. package/dist/ai/codexLogin.js +2 -0
  60. package/dist/ai/codexLogin.js.map +1 -1
  61. package/dist/ai/codexMcpProvider.d.ts.map +1 -1
  62. package/dist/ai/codexMcpProvider.js +2 -0
  63. package/dist/ai/codexMcpProvider.js.map +1 -1
  64. package/dist/ai/commitSummary.d.ts.map +1 -1
  65. package/dist/ai/commitSummary.js +2 -0
  66. package/dist/ai/commitSummary.js.map +1 -1
  67. package/dist/ai/commitSummaryCli.d.ts.map +1 -1
  68. package/dist/ai/commitSummaryCli.js +2 -0
  69. package/dist/ai/commitSummaryCli.js.map +1 -1
  70. package/dist/ai/commitSummaryStore.d.ts.map +1 -1
  71. package/dist/ai/commitSummaryStore.js +2 -0
  72. package/dist/ai/commitSummaryStore.js.map +1 -1
  73. package/dist/ai/contentBlocks.d.ts +9 -0
  74. package/dist/ai/contentBlocks.d.ts.map +1 -0
  75. package/dist/ai/contentBlocks.js +86 -0
  76. package/dist/ai/contentBlocks.js.map +1 -0
  77. package/dist/ai/debugLogger.d.ts.map +1 -1
  78. package/dist/ai/debugLogger.js +2 -0
  79. package/dist/ai/debugLogger.js.map +1 -1
  80. package/dist/ai/enrichEntry.d.ts.map +1 -1
  81. package/dist/ai/enrichEntry.js.map +1 -1
  82. package/dist/ai/pdfMeta.d.ts +8 -0
  83. package/dist/ai/pdfMeta.d.ts.map +1 -0
  84. package/dist/ai/pdfMeta.js +51 -0
  85. package/dist/ai/pdfMeta.js.map +1 -0
  86. package/dist/ai/provider.d.ts +14 -6
  87. package/dist/ai/provider.d.ts.map +1 -1
  88. package/dist/ai/provider.js.map +1 -1
  89. package/dist/ai/sandboxMcp.d.ts.map +1 -1
  90. package/dist/ai/sandboxMcp.js +2 -0
  91. package/dist/ai/sandboxMcp.js.map +1 -1
  92. package/dist/ai/sandboxMcpStdio.d.ts.map +1 -1
  93. package/dist/ai/sandboxMcpStdio.js +2 -0
  94. package/dist/ai/sandboxMcpStdio.js.map +1 -1
  95. package/dist/ai/sessionManager.d.ts +12 -2
  96. package/dist/ai/sessionManager.d.ts.map +1 -1
  97. package/dist/ai/sessionManager.js +39 -5
  98. package/dist/ai/sessionManager.js.map +1 -1
  99. package/dist/ai/sessionRegistry.d.ts.map +1 -1
  100. package/dist/ai/sessionRegistry.js +2 -0
  101. package/dist/ai/sessionRegistry.js.map +1 -1
  102. package/dist/ai/sessionStore.d.ts.map +1 -1
  103. package/dist/ai/sessionStore.js +2 -0
  104. package/dist/ai/sessionStore.js.map +1 -1
  105. package/dist/ai/systemPrompt.d.ts.map +1 -1
  106. package/dist/ai/systemPrompt.js.map +1 -1
  107. package/dist/config.d.ts.map +1 -1
  108. package/dist/config.js +2 -0
  109. package/dist/config.js.map +1 -1
  110. package/dist/connection/connection.d.ts.map +1 -1
  111. package/dist/connection/connection.js +2 -0
  112. package/dist/connection/connection.js.map +1 -1
  113. package/dist/connection/e2eHarness.d.ts.map +1 -1
  114. package/dist/connection/e2eHarness.js +2 -0
  115. package/dist/connection/e2eHarness.js.map +1 -1
  116. package/dist/connection/fakeRelay.d.ts.map +1 -1
  117. package/dist/connection/fakeRelay.js +2 -0
  118. package/dist/connection/fakeRelay.js.map +1 -1
  119. package/dist/connection/pubsub.d.ts.map +1 -1
  120. package/dist/connection/pubsub.js +2 -0
  121. package/dist/connection/pubsub.js.map +1 -1
  122. package/dist/connection/relay.d.ts.map +1 -1
  123. package/dist/connection/relay.js +2 -0
  124. package/dist/connection/relay.js.map +1 -1
  125. package/dist/files/fileBrowser.d.ts.map +1 -1
  126. package/dist/files/fileBrowser.js +2 -0
  127. package/dist/files/fileBrowser.js.map +1 -1
  128. package/dist/git/operations.d.ts.map +1 -1
  129. package/dist/git/operations.js +2 -0
  130. package/dist/git/operations.js.map +1 -1
  131. package/dist/handlers/legacyBusAdapter.d.ts +1 -1
  132. package/dist/handlers/legacyBusAdapter.d.ts.map +1 -1
  133. package/dist/handlers/legacyBusAdapter.js +13 -1
  134. package/dist/handlers/legacyBusAdapter.js.map +1 -1
  135. package/dist/handlers/messageHandler.d.ts +23 -0
  136. package/dist/handlers/messageHandler.d.ts.map +1 -1
  137. package/dist/handlers/messageHandler.js +223 -7
  138. package/dist/handlers/messageHandler.js.map +1 -1
  139. package/dist/index.js +42 -2
  140. package/dist/index.js.map +1 -1
  141. package/dist/messageBus/busServerTransport.d.ts.map +1 -1
  142. package/dist/messageBus/busServerTransport.js +2 -0
  143. package/dist/messageBus/busServerTransport.js.map +1 -1
  144. package/dist/service/debugHttpServer.d.ts.map +1 -1
  145. package/dist/service/debugHttpServer.js +2 -0
  146. package/dist/service/debugHttpServer.js.map +1 -1
  147. package/dist/service/ensureDaemon.d.ts.map +1 -1
  148. package/dist/service/ensureDaemon.js +27 -2
  149. package/dist/service/ensureDaemon.js.map +1 -1
  150. package/dist/service/index.d.ts.map +1 -1
  151. package/dist/service/index.js +2 -0
  152. package/dist/service/index.js.map +1 -1
  153. package/dist/service/ipcClient.d.ts.map +1 -1
  154. package/dist/service/ipcClient.js +3 -1
  155. package/dist/service/ipcClient.js.map +1 -1
  156. package/dist/service/ipcServer.d.ts.map +1 -1
  157. package/dist/service/ipcServer.js +2 -0
  158. package/dist/service/ipcServer.js.map +1 -1
  159. package/dist/service/pushClient.d.ts.map +1 -1
  160. package/dist/service/pushClient.js +2 -0
  161. package/dist/service/pushClient.js.map +1 -1
  162. package/dist/service/run.d.ts.map +1 -1
  163. package/dist/service/run.js +14 -1
  164. package/dist/service/run.js.map +1 -1
  165. package/dist/service/singleton.d.ts +1 -0
  166. package/dist/service/singleton.d.ts.map +1 -1
  167. package/dist/service/singleton.js +5 -0
  168. package/dist/service/singleton.js.map +1 -1
  169. package/dist/service/stateStore.d.ts.map +1 -1
  170. package/dist/service/stateStore.js +2 -0
  171. package/dist/service/stateStore.js.map +1 -1
  172. package/dist/service/systemdUnit.d.ts +149 -0
  173. package/dist/service/systemdUnit.d.ts.map +1 -0
  174. package/dist/service/systemdUnit.js +322 -0
  175. package/dist/service/systemdUnit.js.map +1 -0
  176. package/dist/service/types.d.ts +6 -0
  177. package/dist/service/types.d.ts.map +1 -1
  178. package/dist/service/types.js +3 -1
  179. package/dist/service/types.js.map +1 -1
  180. package/dist/storage/eventStore.d.ts.map +1 -1
  181. package/dist/storage/eventStore.js +2 -0
  182. package/dist/storage/eventStore.js.map +1 -1
  183. package/dist/terminal/terminalManager.d.ts.map +1 -1
  184. package/dist/terminal/terminalManager.js +2 -0
  185. package/dist/terminal/terminalManager.js.map +1 -1
  186. package/dist/tombstoneCheck.d.ts.map +1 -1
  187. package/dist/tombstoneCheck.js +2 -0
  188. package/dist/tombstoneCheck.js.map +1 -1
  189. package/package.json +3 -3
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Quicksave, KingYoung Technology
3
+ Copyright (c) 2026 King Young Technology and contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -47,6 +47,6 @@ just attach to it to add repos or re-read pairing info.
47
47
  - **CLI subcommands, debug commands, data layout** —
48
48
  [`docs/references/agent-cli.md`](../../docs/references/agent-cli.md)
49
49
  - **Architecture (sessions, MessageBus, permissions, IPC)** —
50
- [`docs/references/quicksave-architecture.md`](../../docs/references/quicksave-architecture.md)
50
+ [`docs/references/quicksave-architecture.en.md`](../../docs/references/quicksave-architecture.en.md)
51
51
  - **Local development** —
52
52
  [`docs/development.md`](../../docs/development.md)
@@ -1 +1 @@
1
- {"version":3,"file":"asyncQueue.d.ts","sourceRoot":"","sources":["../../src/ai/asyncQueue.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,qBAAa,UAAU,CAAC,CAAC,CAAE,YAAW,aAAa,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,OAAO,CAAqD;IACpE,OAAO,CAAC,IAAI,CAAS;IAErB,8EAA8E;IAC9E,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI;IAWpB,iDAAiD;IACjD,GAAG,IAAI,IAAI;IASX,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC;CAe3C"}
1
+ {"version":3,"file":"asyncQueue.d.ts","sourceRoot":"","sources":["../../src/ai/asyncQueue.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,qBAAa,UAAU,CAAC,CAAC,CAAE,YAAW,aAAa,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,OAAO,CAAqD;IACpE,OAAO,CAAC,IAAI,CAAS;IAErB,8EAA8E;IAC9E,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI;IAWpB,iDAAiD;IACjD,GAAG,IAAI,IAAI;IASX,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC;CAe3C"}
@@ -1,3 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 King Young Technology
2
+ // SPDX-License-Identifier: MIT
1
3
  /**
2
4
  * A simple async iterable queue for multi-turn prompt delivery.
3
5
  *
@@ -1 +1 @@
1
- {"version":3,"file":"asyncQueue.js","sourceRoot":"","sources":["../../src/ai/asyncQueue.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,OAAO,UAAU;IACb,KAAK,GAAQ,EAAE,CAAC;IAChB,OAAO,GAAgD,IAAI,CAAC;IAC5D,IAAI,GAAG,KAAK,CAAC;IAErB,8EAA8E;IAC9E,IAAI,CAAC,KAAQ;QACX,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO;QACtB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;YAC7B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,iDAAiD;IACjD,GAAG;QACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;YAC7B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,OAAO,CAAC,EAAE,KAAK,EAAE,SAAgB,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAED,CAAC,MAAM,CAAC,aAAa,CAAC;QACpB,OAAO;YACL,IAAI,EAAE,GAA+B,EAAE;gBACrC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC1B,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAG,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;gBACtE,CAAC;gBACD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;oBACd,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,SAAgB,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;gBAClE,CAAC;gBACD,OAAO,IAAI,OAAO,CAAoB,CAAC,OAAO,EAAE,EAAE;oBAChD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;gBACzB,CAAC,CAAC,CAAC;YACL,CAAC;SACF,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"asyncQueue.js","sourceRoot":"","sources":["../../src/ai/asyncQueue.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,+BAA+B;AAC/B;;;;;GAKG;AACH,MAAM,OAAO,UAAU;IACb,KAAK,GAAQ,EAAE,CAAC;IAChB,OAAO,GAAgD,IAAI,CAAC;IAC5D,IAAI,GAAG,KAAK,CAAC;IAErB,8EAA8E;IAC9E,IAAI,CAAC,KAAQ;QACX,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO;QACtB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;YAC7B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,iDAAiD;IACjD,GAAG;QACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;YAC7B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,OAAO,CAAC,EAAE,KAAK,EAAE,SAAgB,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAED,CAAC,MAAM,CAAC,aAAa,CAAC;QACpB,OAAO;YACL,IAAI,EAAE,GAA+B,EAAE;gBACrC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC1B,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAG,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;gBACtE,CAAC;gBACD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;oBACd,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,SAAgB,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;gBAClE,CAAC;gBACD,OAAO,IAAI,OAAO,CAAoB,CAAC,OAAO,EAAE,EAAE;oBAChD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;gBACzB,CAAC,CAAC,CAAC;YACL,CAAC;SACF,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,71 @@
1
+ import { type Attachment, type AttachmentUploadRequestPayload, type AttachmentUploadResponsePayload } from '@sumicom/quicksave-shared';
2
+ export interface AttachmentNotFoundError extends Error {
3
+ code: 'attachment_not_found';
4
+ attachmentId: string;
5
+ }
6
+ export interface AttachmentNotReadyError extends Error {
7
+ code: 'attachment_not_ready';
8
+ attachmentId: string;
9
+ }
10
+ export interface AttachmentTooLargeError extends Error {
11
+ code: 'attachment_too_large';
12
+ attachmentId: string;
13
+ }
14
+ export interface AttachmentTooManyPagesError extends Error {
15
+ code: 'attachment_too_many_pages';
16
+ attachmentId: string;
17
+ }
18
+ export interface AttachmentBadRequestError extends Error {
19
+ code: 'attachment_bad_request';
20
+ attachmentId: string;
21
+ }
22
+ export interface AttachmentPeerQuotaError extends Error {
23
+ code: 'attachment_peer_quota';
24
+ }
25
+ export interface AttachmentStagingOptions {
26
+ /** Override TTL — primarily for tests. */
27
+ ttlMs?: number;
28
+ /** Override per-peer cap — primarily for tests. */
29
+ perPeerMaxBytes?: number;
30
+ /** Custom clock — primarily for tests. */
31
+ now?: () => number;
32
+ }
33
+ /**
34
+ * In-memory staging map keyed by `(peerAddress, attachmentId)`. One instance
35
+ * per agent process; the messageHandler injects the peer address on every
36
+ * request.
37
+ */
38
+ export declare class AttachmentStaging {
39
+ private readonly byPeer;
40
+ private readonly perPeerBytes;
41
+ private readonly ttlMs;
42
+ private readonly perPeerMaxBytes;
43
+ private readonly now;
44
+ constructor(opts?: AttachmentStagingOptions);
45
+ /**
46
+ * Apply one upload chunk. Returns the running progress + ready flag.
47
+ * Throws a tagged Error (`code` field) for validation failures so the
48
+ * messageHandler can map them to bus error responses.
49
+ */
50
+ acceptChunk(peerAddress: string, payload: AttachmentUploadRequestPayload): AttachmentUploadResponsePayload;
51
+ /**
52
+ * Atomically remove and return the requested attachments. Throws on the
53
+ * first missing or not-ready id (with that id in the error). On error,
54
+ * **no** attachments are consumed — callers can retry safely.
55
+ */
56
+ consume(peerAddress: string, attachmentIds: readonly string[]): Attachment[];
57
+ /** Drop a staged attachment if present. Returns true if anything was removed. */
58
+ cancel(peerAddress: string, attachmentId: string): boolean;
59
+ /** Drop every staging record for a peer (called on disconnect). */
60
+ removePeer(peerAddress: string): void;
61
+ /** Sweep expired entries. Safe to call from a periodic timer. */
62
+ gc(): void;
63
+ /** Test/diagnostic: count of staged records for a peer. */
64
+ size(peerAddress: string): number;
65
+ /** Test/diagnostic: bytes currently held for a peer. */
66
+ bytesFor(peerAddress: string): number;
67
+ private validateMeta;
68
+ private isReady;
69
+ private dropEntry;
70
+ }
71
+ //# sourceMappingURL=attachmentStaging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachmentStaging.d.ts","sourceRoot":"","sources":["../../src/ai/attachmentStaging.ts"],"names":[],"mappings":"AASA,OAAO,EAKL,KAAK,UAAU,EAEf,KAAK,8BAA8B,EACnC,KAAK,+BAA+B,EACrC,MAAM,2BAA2B,CAAC;AAqBnC,MAAM,WAAW,uBAAwB,SAAQ,KAAK;IACpD,IAAI,EAAE,sBAAsB,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;CACtB;AACD,MAAM,WAAW,uBAAwB,SAAQ,KAAK;IACpD,IAAI,EAAE,sBAAsB,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;CACtB;AACD,MAAM,WAAW,uBAAwB,SAAQ,KAAK;IACpD,IAAI,EAAE,sBAAsB,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;CACtB;AACD,MAAM,WAAW,2BAA4B,SAAQ,KAAK;IACxD,IAAI,EAAE,2BAA2B,CAAC;IAClC,YAAY,EAAE,MAAM,CAAC;CACtB;AACD,MAAM,WAAW,yBAA0B,SAAQ,KAAK;IACtD,IAAI,EAAE,wBAAwB,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;CACtB;AACD,MAAM,WAAW,wBAAyB,SAAQ,KAAK;IACrD,IAAI,EAAE,uBAAuB,CAAC;CAC/B;AAqBD,MAAM,WAAW,wBAAwB;IACvC,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,0CAA0C;IAC1C,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoD;IAC3E,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6B;IAC1D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;gBAEvB,IAAI,GAAE,wBAA6B;IAM/C;;;;OAIG;IACH,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,8BAA8B,GAAG,+BAA+B;IA2G1G;;;;OAIG;IACH,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,EAAE;IA6B5E,iFAAiF;IACjF,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO;IAI1D,mEAAmE;IACnE,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAKrC,iEAAiE;IACjE,EAAE,IAAI,IAAI;IAeV,2DAA2D;IAC3D,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;IAIjC,wDAAwD;IACxD,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;IAMrC,OAAO,CAAC,YAAY;IAqBpB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,SAAS;CAiBlB"}
@@ -0,0 +1,243 @@
1
+ // SPDX-FileCopyrightText: 2026 King Young Technology
2
+ // SPDX-License-Identifier: MIT
3
+ // ============================================================================
4
+ // Attachment staging — buffers chunked uploads from a peer until they are
5
+ // consumed by a `claude:start` / `claude:resume` whose payload references
6
+ // the attachment ids. Buffers live in memory; the GC loop drops idle records
7
+ // after `ATTACHMENT_STAGING_TTL_MS`.
8
+ // ============================================================================
9
+ import { ATTACHMENT_LIMITS, ATTACHMENT_STAGING_TTL_MS, PDF_MAX_PAGES, PER_PEER_STAGING_MAX_BYTES, } from '@sumicom/quicksave-shared';
10
+ import { countPdfPages } from './pdfMeta.js';
11
+ function makeError(code, message, extra = {}) {
12
+ const err = new Error(message);
13
+ err.code = code;
14
+ Object.assign(err, extra);
15
+ return err;
16
+ }
17
+ /**
18
+ * In-memory staging map keyed by `(peerAddress, attachmentId)`. One instance
19
+ * per agent process; the messageHandler injects the peer address on every
20
+ * request.
21
+ */
22
+ export class AttachmentStaging {
23
+ byPeer = new Map();
24
+ perPeerBytes = new Map();
25
+ ttlMs;
26
+ perPeerMaxBytes;
27
+ now;
28
+ constructor(opts = {}) {
29
+ this.ttlMs = opts.ttlMs ?? ATTACHMENT_STAGING_TTL_MS;
30
+ this.perPeerMaxBytes = opts.perPeerMaxBytes ?? PER_PEER_STAGING_MAX_BYTES;
31
+ this.now = opts.now ?? (() => Date.now());
32
+ }
33
+ /**
34
+ * Apply one upload chunk. Returns the running progress + ready flag.
35
+ * Throws a tagged Error (`code` field) for validation failures so the
36
+ * messageHandler can map them to bus error responses.
37
+ */
38
+ acceptChunk(peerAddress, payload) {
39
+ const { attachmentId, chunkIndex, chunk, meta } = payload;
40
+ if (!attachmentId || typeof attachmentId !== 'string') {
41
+ throw makeError('attachment_bad_request', 'attachmentId required', { attachmentId: String(attachmentId) });
42
+ }
43
+ if (typeof chunkIndex !== 'number' || chunkIndex < 0 || !Number.isInteger(chunkIndex)) {
44
+ throw makeError('attachment_bad_request', 'chunkIndex must be a non-negative integer', { attachmentId });
45
+ }
46
+ if (typeof chunk !== 'string') {
47
+ throw makeError('attachment_bad_request', 'chunk must be base64 string', { attachmentId });
48
+ }
49
+ const peerMap = this.byPeer.get(peerAddress) ?? new Map();
50
+ let staged = peerMap.get(attachmentId);
51
+ if (!staged) {
52
+ // First time we see this id — meta is required.
53
+ if (!meta) {
54
+ throw makeError('attachment_bad_request', 'meta required on first chunk', { attachmentId });
55
+ }
56
+ this.validateMeta(attachmentId, meta);
57
+ staged = {
58
+ attachmentId,
59
+ kind: meta.kind,
60
+ mimeType: meta.mimeType,
61
+ name: meta.name,
62
+ size: meta.size,
63
+ totalChunks: meta.totalChunks,
64
+ chunks: new Array(meta.totalChunks),
65
+ receivedBytes: 0,
66
+ receivedCount: 0,
67
+ lastTouchedAt: this.now(),
68
+ };
69
+ peerMap.set(attachmentId, staged);
70
+ this.byPeer.set(peerAddress, peerMap);
71
+ }
72
+ else if (meta) {
73
+ // Subsequent chunks may include meta but must be consistent.
74
+ if (meta.kind !== staged.kind
75
+ || meta.mimeType !== staged.mimeType
76
+ || meta.name !== staged.name
77
+ || meta.size !== staged.size
78
+ || meta.totalChunks !== staged.totalChunks) {
79
+ throw makeError('attachment_bad_request', 'meta mismatch for existing attachment', { attachmentId });
80
+ }
81
+ }
82
+ if (chunkIndex >= staged.totalChunks) {
83
+ throw makeError('attachment_bad_request', `chunkIndex ${chunkIndex} >= totalChunks ${staged.totalChunks}`, { attachmentId });
84
+ }
85
+ if (staged.chunks[chunkIndex] !== undefined) {
86
+ // Idempotent re-send: if the bytes match, no-op; otherwise reject.
87
+ const existing = staged.chunks[chunkIndex];
88
+ const incoming = Buffer.from(chunk, 'base64');
89
+ if (existing.equals(incoming)) {
90
+ staged.lastTouchedAt = this.now();
91
+ return { attachmentId, receivedBytes: staged.receivedBytes, ready: this.isReady(staged) };
92
+ }
93
+ throw makeError('attachment_bad_request', `chunk ${chunkIndex} already received with different bytes`, { attachmentId });
94
+ }
95
+ const buf = Buffer.from(chunk, 'base64');
96
+ const nextRunningBytes = staged.receivedBytes + buf.length;
97
+ if (nextRunningBytes > staged.size) {
98
+ throw makeError('attachment_too_large', `running bytes exceeds declared size`, { attachmentId });
99
+ }
100
+ const peerTotal = this.perPeerBytes.get(peerAddress) ?? 0;
101
+ if (peerTotal + buf.length > this.perPeerMaxBytes) {
102
+ throw makeError('attachment_peer_quota', 'per-peer staging quota exceeded');
103
+ }
104
+ staged.chunks[chunkIndex] = buf;
105
+ staged.receivedBytes = nextRunningBytes;
106
+ staged.receivedCount += 1;
107
+ staged.lastTouchedAt = this.now();
108
+ this.perPeerBytes.set(peerAddress, peerTotal + buf.length);
109
+ const ready = this.isReady(staged);
110
+ if (ready && staged.receivedBytes !== staged.size) {
111
+ // Strict: declared size must match received bytes when ready.
112
+ this.dropEntry(peerAddress, attachmentId);
113
+ throw makeError('attachment_bad_request', 'received bytes do not match declared size', { attachmentId });
114
+ }
115
+ // Page-count check on PDF completion. The Anthropic API rejects PDFs over
116
+ // PDF_MAX_PAGES and the SDK rewrites the rejection as a poison "PDF too
117
+ // large" assistant block — drop the entry now so the user sees a clean
118
+ // error instead of a stuck session. countPdfPages returns null/0 for
119
+ // PDFs where pages live in compressed object streams (rare); in that
120
+ // case we let it through and fall back to the recovery card path.
121
+ if (ready && staged.kind === 'pdf') {
122
+ const pages = countPdfPages(Buffer.concat(staged.chunks));
123
+ if (pages !== null && pages > PDF_MAX_PAGES) {
124
+ this.dropEntry(peerAddress, attachmentId);
125
+ throw makeError('attachment_too_many_pages', `PDF has ${pages} pages (max ${PDF_MAX_PAGES})`, { attachmentId });
126
+ }
127
+ }
128
+ return { attachmentId, receivedBytes: staged.receivedBytes, ready };
129
+ }
130
+ /**
131
+ * Atomically remove and return the requested attachments. Throws on the
132
+ * first missing or not-ready id (with that id in the error). On error,
133
+ * **no** attachments are consumed — callers can retry safely.
134
+ */
135
+ consume(peerAddress, attachmentIds) {
136
+ if (attachmentIds.length === 0)
137
+ return [];
138
+ const peerMap = this.byPeer.get(peerAddress);
139
+ if (!peerMap) {
140
+ throw makeError('attachment_not_found', `no staged attachments for peer`, { attachmentId: attachmentIds[0] });
141
+ }
142
+ // Validate all first, then remove.
143
+ for (const id of attachmentIds) {
144
+ const s = peerMap.get(id);
145
+ if (!s)
146
+ throw makeError('attachment_not_found', `attachment ${id} not staged`, { attachmentId: id });
147
+ if (!this.isReady(s))
148
+ throw makeError('attachment_not_ready', `attachment ${id} not ready`, { attachmentId: id });
149
+ }
150
+ const result = [];
151
+ for (const id of attachmentIds) {
152
+ const s = peerMap.get(id);
153
+ const data = Buffer.concat(s.chunks).toString('base64');
154
+ result.push({
155
+ id: s.attachmentId,
156
+ kind: s.kind,
157
+ mimeType: s.mimeType,
158
+ name: s.name,
159
+ size: s.size,
160
+ data,
161
+ });
162
+ this.dropEntry(peerAddress, id);
163
+ }
164
+ return result;
165
+ }
166
+ /** Drop a staged attachment if present. Returns true if anything was removed. */
167
+ cancel(peerAddress, attachmentId) {
168
+ return this.dropEntry(peerAddress, attachmentId);
169
+ }
170
+ /** Drop every staging record for a peer (called on disconnect). */
171
+ removePeer(peerAddress) {
172
+ this.byPeer.delete(peerAddress);
173
+ this.perPeerBytes.delete(peerAddress);
174
+ }
175
+ /** Sweep expired entries. Safe to call from a periodic timer. */
176
+ gc() {
177
+ const cutoff = this.now() - this.ttlMs;
178
+ for (const [peer, map] of this.byPeer) {
179
+ for (const [id, s] of map) {
180
+ if (s.lastTouchedAt <= cutoff) {
181
+ this.dropEntry(peer, id);
182
+ }
183
+ }
184
+ if (map.size === 0) {
185
+ this.byPeer.delete(peer);
186
+ this.perPeerBytes.delete(peer);
187
+ }
188
+ }
189
+ }
190
+ /** Test/diagnostic: count of staged records for a peer. */
191
+ size(peerAddress) {
192
+ return this.byPeer.get(peerAddress)?.size ?? 0;
193
+ }
194
+ /** Test/diagnostic: bytes currently held for a peer. */
195
+ bytesFor(peerAddress) {
196
+ return this.perPeerBytes.get(peerAddress) ?? 0;
197
+ }
198
+ // ── Private ─────────────────────────────────────────────────────────────
199
+ validateMeta(attachmentId, meta) {
200
+ if (!meta.kind || !ATTACHMENT_LIMITS[meta.kind]) {
201
+ throw makeError('attachment_bad_request', `unknown kind`, { attachmentId });
202
+ }
203
+ if (typeof meta.size !== 'number' || meta.size <= 0 || !Number.isFinite(meta.size)) {
204
+ throw makeError('attachment_bad_request', 'invalid size', { attachmentId });
205
+ }
206
+ if (meta.size > ATTACHMENT_LIMITS[meta.kind].maxBytes) {
207
+ throw makeError('attachment_too_large', `${meta.kind} exceeds ${ATTACHMENT_LIMITS[meta.kind].maxBytes} bytes`, { attachmentId });
208
+ }
209
+ if (typeof meta.totalChunks !== 'number' || meta.totalChunks <= 0 || !Number.isInteger(meta.totalChunks)) {
210
+ throw makeError('attachment_bad_request', 'invalid totalChunks', { attachmentId });
211
+ }
212
+ if (typeof meta.mimeType !== 'string' || meta.mimeType.length === 0) {
213
+ throw makeError('attachment_bad_request', 'invalid mimeType', { attachmentId });
214
+ }
215
+ if (typeof meta.name !== 'string' || meta.name.length === 0) {
216
+ throw makeError('attachment_bad_request', 'invalid name', { attachmentId });
217
+ }
218
+ }
219
+ isReady(s) {
220
+ return s.receivedCount === s.totalChunks;
221
+ }
222
+ dropEntry(peerAddress, attachmentId) {
223
+ const peerMap = this.byPeer.get(peerAddress);
224
+ if (!peerMap)
225
+ return false;
226
+ const s = peerMap.get(attachmentId);
227
+ if (!s)
228
+ return false;
229
+ peerMap.delete(attachmentId);
230
+ const remainingBytes = (this.perPeerBytes.get(peerAddress) ?? 0) - s.receivedBytes;
231
+ if (remainingBytes > 0) {
232
+ this.perPeerBytes.set(peerAddress, remainingBytes);
233
+ }
234
+ else {
235
+ this.perPeerBytes.delete(peerAddress);
236
+ }
237
+ if (peerMap.size === 0) {
238
+ this.byPeer.delete(peerAddress);
239
+ }
240
+ return true;
241
+ }
242
+ }
243
+ //# sourceMappingURL=attachmentStaging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachmentStaging.js","sourceRoot":"","sources":["../../src/ai/attachmentStaging.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import type { Attachment, AttachmentMetadata } from '@sumicom/quicksave-shared';
2
+ export interface PersistedMeta {
3
+ id: string;
4
+ kind: AttachmentMetadata['kind'];
5
+ mimeType: string;
6
+ name: string;
7
+ size: number;
8
+ storedAt: number;
9
+ }
10
+ /**
11
+ * Persist a batch of resolved attachments under one session id. Idempotent
12
+ * per id — re-writing the same id overwrites both files.
13
+ */
14
+ export declare function persistAttachments(sessionId: string, attachments: readonly Attachment[]): Promise<void>;
15
+ export interface TurnManifestEntry {
16
+ ids: string[];
17
+ }
18
+ /**
19
+ * Read the per-session attachment turn manifest in send order. Returns an
20
+ * empty array if no manifest exists yet (e.g. a session whose attachments
21
+ * predate this code), letting callers fall back to fuzzy rebind.
22
+ */
23
+ export declare function readTurnManifest(sessionId: string): Promise<TurnManifestEntry[]>;
24
+ /**
25
+ * Read one attachment's bytes back, returning the wire `Attachment` shape
26
+ * (metadata + base64 data). Returns `null` if the attachment isn't on disk
27
+ * — e.g. session was end-tasked, or the JSONL had an attachment we didn't
28
+ * persist (cold-start session before this code shipped).
29
+ */
30
+ export declare function loadAttachment(sessionId: string, attachmentId: string): Promise<Attachment | null>;
31
+ /** Drop every persisted attachment for one session (called on end-task). */
32
+ export declare function removeSessionAttachments(sessionId: string): Promise<void>;
33
+ /**
34
+ * List metadata for every attachment persisted under a session id. Mainly
35
+ * for diagnostics / tests.
36
+ */
37
+ export declare function listSessionAttachments(sessionId: string): Promise<PersistedMeta[]>;
38
+ /** True if the meta+bin pair exist on disk — without reading the bytes. */
39
+ export declare function hasPersistedAttachment(sessionId: string, attachmentId: string): Promise<boolean>;
40
+ //# sourceMappingURL=attachmentStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachmentStore.d.ts","sourceRoot":"","sources":["../../src/ai/attachmentStore.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAGhF,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAkBD;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,SAAS,UAAU,EAAE,GACjC,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,EAAE,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAoBtF;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAyB5B;AAED,4EAA4E;AAC5E,wBAAsB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM/E;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAkBxF;AAED,2EAA2E;AAC3E,wBAAsB,sBAAsB,CAC1C,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,OAAO,CAAC,CAUlB"}
@@ -0,0 +1,173 @@
1
+ // SPDX-FileCopyrightText: 2026 King Young Technology
2
+ // SPDX-License-Identifier: MIT
3
+ // ============================================================================
4
+ // Persistent attachment store on the agent.
5
+ //
6
+ // Once `attachmentStaging.consume(...)` materializes an `Attachment[]` for a
7
+ // `claude:start` / `claude:resume`, the messageHandler also writes each
8
+ // attachment to disk under
9
+ //
10
+ // <state>/attachments/<sessionId>/<attachmentId>.bin (base64-decoded bytes)
11
+ // <state>/attachments/<sessionId>/<attachmentId>.meta.json
12
+ //
13
+ // The PWA fetches bytes on demand via `attachment:fetch { sessionId, id }`,
14
+ // caches them in `attachmentCache` (L1/L2), and renders chip thumbnails
15
+ // without dragging the data through every card-history snapshot.
16
+ //
17
+ // Cleanup happens on session end-task: `removeSessionAttachments(sessionId)`
18
+ // nukes the directory.
19
+ // ============================================================================
20
+ import { mkdir, readFile, writeFile, appendFile, rm, readdir, stat } from 'fs/promises';
21
+ import { join } from 'path';
22
+ import { getAttachmentsDir } from '../service/singleton.js';
23
+ function dirFor(sessionId) {
24
+ return join(getAttachmentsDir(), sessionId);
25
+ }
26
+ function binPathFor(sessionId, attachmentId) {
27
+ return join(dirFor(sessionId), `${attachmentId}.bin`);
28
+ }
29
+ function metaPathFor(sessionId, attachmentId) {
30
+ return join(dirFor(sessionId), `${attachmentId}.meta.json`);
31
+ }
32
+ function turnManifestPathFor(sessionId) {
33
+ return join(dirFor(sessionId), 'turn-manifest.jsonl');
34
+ }
35
+ /**
36
+ * Persist a batch of resolved attachments under one session id. Idempotent
37
+ * per id — re-writing the same id overwrites both files.
38
+ */
39
+ export async function persistAttachments(sessionId, attachments) {
40
+ if (attachments.length === 0)
41
+ return;
42
+ await mkdir(dirFor(sessionId), { recursive: true });
43
+ await Promise.all(attachments.map(async (a) => {
44
+ const bytes = Buffer.from(a.data, 'base64');
45
+ await writeFile(binPathFor(sessionId, a.id), bytes);
46
+ const meta = {
47
+ id: a.id,
48
+ kind: a.kind,
49
+ mimeType: a.mimeType,
50
+ name: a.name,
51
+ size: a.size,
52
+ storedAt: Date.now(),
53
+ };
54
+ await writeFile(metaPathFor(sessionId, a.id), JSON.stringify(meta));
55
+ }));
56
+ // Append a turn-manifest line so the cardBuilder can rebind on JSONL replay
57
+ // by exact UUID instead of falling back to fuzzy (kind+size+name) match.
58
+ // One line per attachment-bearing user turn, in send order.
59
+ const line = JSON.stringify({ ids: attachments.map((a) => a.id) }) + '\n';
60
+ await appendFile(turnManifestPathFor(sessionId), line);
61
+ }
62
+ /**
63
+ * Read the per-session attachment turn manifest in send order. Returns an
64
+ * empty array if no manifest exists yet (e.g. a session whose attachments
65
+ * predate this code), letting callers fall back to fuzzy rebind.
66
+ */
67
+ export async function readTurnManifest(sessionId) {
68
+ let raw;
69
+ try {
70
+ raw = await readFile(turnManifestPathFor(sessionId), 'utf8');
71
+ }
72
+ catch {
73
+ return [];
74
+ }
75
+ const out = [];
76
+ for (const line of raw.split('\n')) {
77
+ if (!line.trim())
78
+ continue;
79
+ try {
80
+ const parsed = JSON.parse(line);
81
+ if (parsed && Array.isArray(parsed.ids) && parsed.ids.every((x) => typeof x === 'string')) {
82
+ out.push({ ids: parsed.ids });
83
+ }
84
+ }
85
+ catch {
86
+ // skip malformed line — don't break the whole replay
87
+ }
88
+ }
89
+ return out;
90
+ }
91
+ /**
92
+ * Read one attachment's bytes back, returning the wire `Attachment` shape
93
+ * (metadata + base64 data). Returns `null` if the attachment isn't on disk
94
+ * — e.g. session was end-tasked, or the JSONL had an attachment we didn't
95
+ * persist (cold-start session before this code shipped).
96
+ */
97
+ export async function loadAttachment(sessionId, attachmentId) {
98
+ let metaRaw;
99
+ let bytes;
100
+ try {
101
+ [metaRaw, bytes] = await Promise.all([
102
+ readFile(metaPathFor(sessionId, attachmentId), 'utf8'),
103
+ readFile(binPathFor(sessionId, attachmentId)),
104
+ ]);
105
+ }
106
+ catch {
107
+ return null;
108
+ }
109
+ let meta;
110
+ try {
111
+ meta = JSON.parse(metaRaw);
112
+ }
113
+ catch {
114
+ return null;
115
+ }
116
+ return {
117
+ id: meta.id,
118
+ kind: meta.kind,
119
+ mimeType: meta.mimeType,
120
+ name: meta.name,
121
+ size: meta.size,
122
+ data: bytes.toString('base64'),
123
+ };
124
+ }
125
+ /** Drop every persisted attachment for one session (called on end-task). */
126
+ export async function removeSessionAttachments(sessionId) {
127
+ try {
128
+ await rm(dirFor(sessionId), { recursive: true, force: true });
129
+ }
130
+ catch {
131
+ // best effort — orphaned files are tolerable, they're local-only
132
+ }
133
+ }
134
+ /**
135
+ * List metadata for every attachment persisted under a session id. Mainly
136
+ * for diagnostics / tests.
137
+ */
138
+ export async function listSessionAttachments(sessionId) {
139
+ let entries;
140
+ try {
141
+ entries = await readdir(dirFor(sessionId));
142
+ }
143
+ catch {
144
+ return [];
145
+ }
146
+ const metas = [];
147
+ for (const name of entries) {
148
+ if (!name.endsWith('.meta.json'))
149
+ continue;
150
+ try {
151
+ const raw = await readFile(join(dirFor(sessionId), name), 'utf8');
152
+ metas.push(JSON.parse(raw));
153
+ }
154
+ catch {
155
+ // skip unreadable metas
156
+ }
157
+ }
158
+ return metas;
159
+ }
160
+ /** True if the meta+bin pair exist on disk — without reading the bytes. */
161
+ export async function hasPersistedAttachment(sessionId, attachmentId) {
162
+ try {
163
+ await Promise.all([
164
+ stat(metaPathFor(sessionId, attachmentId)),
165
+ stat(binPathFor(sessionId, attachmentId)),
166
+ ]);
167
+ return true;
168
+ }
169
+ catch {
170
+ return false;
171
+ }
172
+ }
173
+ //# sourceMappingURL=attachmentStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachmentStore.js","sourceRoot":"","sources":["../../src/ai/attachmentStore.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { Card, CardId, CardEvent, CardHistoryResponse, PendingInputAttachment } from '@sumicom/quicksave-shared';
1
+ import type { Attachment, Card, CardId, CardEvent, CardHistoryResponse, PendingInputAttachment } from '@sumicom/quicksave-shared';
2
2
  /**
3
3
  * Load persisted card history for a memory-mode session.
4
4
  * Returns cards in insertion order, or empty array if none exist.
@@ -67,7 +67,7 @@ export declare class StreamCardBuilder {
67
67
  private updateEvent;
68
68
  private appendTextEvent;
69
69
  private removeEvent;
70
- userMessage(text: string): CardEvent;
70
+ userMessage(text: string, attachments?: readonly Attachment[]): CardEvent;
71
71
  thinkingBlock(text: string): CardEvent;
72
72
  /**
73
73
  * Append text to current assistant_text card, or create a new one.
@@ -106,6 +106,7 @@ export declare class StreamCardBuilder {
106
106
  subagentProgress(agentId: string, toolUseId: string | undefined, toolUseCount?: number, lastToolName?: string): CardEvent | null;
107
107
  subagentEnd(agentId: string, toolUseId: string | undefined, status: 'completed' | 'failed' | 'stopped', summary?: string): CardEvent | null;
108
108
  systemMessage(text: string, subtype?: 'compacted' | 'cost' | 'error' | 'info' | 'warning'): CardEvent;
109
+ recoverySuggested(reason: string, action: 'compact', label: string): CardEvent;
109
110
  errorMessage(text: string): CardEvent;
110
111
  }
111
112
  export declare function buildCardsFromHistory(sessionId: string, cwd: string, offset?: number, limit?: number, cutoffBytes?: number): Promise<CardHistoryResponse>;
@@ -1 +1 @@
1
- {"version":3,"file":"cardBuilder.d.ts","sourceRoot":"","sources":["../../src/ai/cardBuilder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cardBuilder.d.ts","sourceRoot":"","sources":["../../src/ai/cardBuilder.ts"],"names":[],"mappings":"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"}