@lapis-notes/ai 0.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 (266) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/LICENSE.md +8 -0
  3. package/README.md +20 -0
  4. package/dist/ai-plugin.d.ts +88 -0
  5. package/dist/ai-plugin.js +742 -0
  6. package/dist/bootstrap/build.d.ts +15 -0
  7. package/dist/bootstrap/build.js +28 -0
  8. package/dist/bootstrap/folder-instructions.d.ts +4 -0
  9. package/dist/bootstrap/folder-instructions.js +49 -0
  10. package/dist/bootstrap/format.d.ts +2 -0
  11. package/dist/bootstrap/format.js +46 -0
  12. package/dist/bootstrap/instructions.d.ts +1 -0
  13. package/dist/bootstrap/instructions.js +8 -0
  14. package/dist/bootstrap/types.d.ts +36 -0
  15. package/dist/bootstrap/types.js +3 -0
  16. package/dist/catalog/ai-catalog-panel.svelte +742 -0
  17. package/dist/catalog/ai-catalog-panel.svelte.d.ts +13 -0
  18. package/dist/catalog/ai-catalog-view-type.d.ts +1 -0
  19. package/dist/catalog/ai-catalog-view-type.js +1 -0
  20. package/dist/catalog/ai-catalog-view.d.ts +22 -0
  21. package/dist/catalog/ai-catalog-view.js +48 -0
  22. package/dist/catalog/filter.d.ts +3 -0
  23. package/dist/catalog/filter.js +24 -0
  24. package/dist/catalog/inventory.d.ts +21 -0
  25. package/dist/catalog/inventory.js +255 -0
  26. package/dist/catalog/tree.d.ts +12 -0
  27. package/dist/catalog/tree.js +60 -0
  28. package/dist/catalog/types.d.ts +44 -0
  29. package/dist/catalog/types.js +1 -0
  30. package/dist/chat/ai-approval-card.svelte +54 -0
  31. package/dist/chat/ai-approval-card.svelte.d.ts +9 -0
  32. package/dist/chat/ai-chat-panel.svelte +1288 -0
  33. package/dist/chat/ai-chat-panel.svelte.d.ts +50 -0
  34. package/dist/chat/ai-inventory-result.css +55 -0
  35. package/dist/chat/ai-inventory-result.svelte +63 -0
  36. package/dist/chat/ai-inventory-result.svelte.d.ts +5 -0
  37. package/dist/chat/ai-question-card.svelte +132 -0
  38. package/dist/chat/ai-question-card.svelte.d.ts +9 -0
  39. package/dist/chat/ai-view-bootstrap.d.ts +13 -0
  40. package/dist/chat/ai-view-bootstrap.js +86 -0
  41. package/dist/chat/ai-view-panel.svelte +89 -0
  42. package/dist/chat/ai-view-panel.svelte.d.ts +13 -0
  43. package/dist/chat/ai-view-type.d.ts +1 -0
  44. package/dist/chat/ai-view-type.js +1 -0
  45. package/dist/chat/ai-view.d.ts +60 -0
  46. package/dist/chat/ai-view.js +121 -0
  47. package/dist/chat/chat-controller.svelte.d.ts +82 -0
  48. package/dist/chat/chat-controller.svelte.js +1926 -0
  49. package/dist/chat/chat-items.d.ts +88 -0
  50. package/dist/chat/chat-items.js +9 -0
  51. package/dist/chat/chat-mentions.d.ts +15 -0
  52. package/dist/chat/chat-mentions.js +77 -0
  53. package/dist/chat/chat-result-views.d.ts +5 -0
  54. package/dist/chat/chat-result-views.js +15 -0
  55. package/dist/chat/chat-session.d.ts +28 -0
  56. package/dist/chat/chat-session.js +50 -0
  57. package/dist/chat/chat-status.d.ts +1 -0
  58. package/dist/chat/chat-status.js +3 -0
  59. package/dist/chat/chat-time.d.ts +18 -0
  60. package/dist/chat/chat-time.js +90 -0
  61. package/dist/chat/chat-tool-display.d.ts +17 -0
  62. package/dist/chat/chat-tool-display.js +213 -0
  63. package/dist/chat/chat-tool-identity.d.ts +4 -0
  64. package/dist/chat/chat-tool-identity.js +42 -0
  65. package/dist/chat/chat-trace.d.ts +6 -0
  66. package/dist/chat/chat-trace.js +256 -0
  67. package/dist/chat/live-runtime-unavailable.d.ts +1 -0
  68. package/dist/chat/live-runtime-unavailable.js +1 -0
  69. package/dist/commands/agent.d.ts +8 -0
  70. package/dist/commands/agent.js +38 -0
  71. package/dist/commands/catalog.d.ts +18 -0
  72. package/dist/commands/catalog.js +115 -0
  73. package/dist/commands/discovery.d.ts +36 -0
  74. package/dist/commands/discovery.js +151 -0
  75. package/dist/commands/groups.d.ts +16 -0
  76. package/dist/commands/groups.js +121 -0
  77. package/dist/commands/inspect.d.ts +18 -0
  78. package/dist/commands/inspect.js +29 -0
  79. package/dist/commands/markdown.d.ts +21 -0
  80. package/dist/commands/markdown.js +117 -0
  81. package/dist/commands/parser.d.ts +4 -0
  82. package/dist/commands/parser.js +24 -0
  83. package/dist/commands/reserved.d.ts +4 -0
  84. package/dist/commands/reserved.js +107 -0
  85. package/dist/commands/router.d.ts +17 -0
  86. package/dist/commands/router.js +170 -0
  87. package/dist/commands/seed.d.ts +4 -0
  88. package/dist/commands/seed.js +8 -0
  89. package/dist/commands/types.d.ts +54 -0
  90. package/dist/commands/types.js +1 -0
  91. package/dist/commands/user-agents-node.d.ts +3 -0
  92. package/dist/commands/user-agents-node.js +52 -0
  93. package/dist/commands/user-agents.d.ts +22 -0
  94. package/dist/commands/user-agents.js +40 -0
  95. package/dist/conversations/approval-grants.d.ts +20 -0
  96. package/dist/conversations/approval-grants.js +75 -0
  97. package/dist/conversations/binding-state.d.ts +6 -0
  98. package/dist/conversations/binding-state.js +35 -0
  99. package/dist/conversations/context-handoff.d.ts +25 -0
  100. package/dist/conversations/context-handoff.js +207 -0
  101. package/dist/conversations/conversation-index-coordinator.d.ts +18 -0
  102. package/dist/conversations/conversation-index-coordinator.js +81 -0
  103. package/dist/conversations/conversation-index.d.ts +16 -0
  104. package/dist/conversations/conversation-index.js +125 -0
  105. package/dist/conversations/conversation-locator.d.ts +2 -0
  106. package/dist/conversations/conversation-locator.js +20 -0
  107. package/dist/conversations/conversation-palette.d.ts +18 -0
  108. package/dist/conversations/conversation-palette.js +29 -0
  109. package/dist/conversations/conversation-repository.d.ts +39 -0
  110. package/dist/conversations/conversation-repository.js +213 -0
  111. package/dist/conversations/handoff-summary.d.ts +48 -0
  112. package/dist/conversations/handoff-summary.js +269 -0
  113. package/dist/conversations/hashes.d.ts +5 -0
  114. package/dist/conversations/hashes.js +40 -0
  115. package/dist/conversations/history-creation-scope.d.ts +12 -0
  116. package/dist/conversations/history-creation-scope.js +44 -0
  117. package/dist/conversations/jsonl.d.ts +10 -0
  118. package/dist/conversations/jsonl.js +41 -0
  119. package/dist/conversations/memory-transcript-store.d.ts +15 -0
  120. package/dist/conversations/memory-transcript-store.js +119 -0
  121. package/dist/conversations/paths.d.ts +14 -0
  122. package/dist/conversations/paths.js +92 -0
  123. package/dist/conversations/redaction.d.ts +13 -0
  124. package/dist/conversations/redaction.js +94 -0
  125. package/dist/conversations/reveal-scope.d.ts +3 -0
  126. package/dist/conversations/reveal-scope.js +8 -0
  127. package/dist/conversations/scope-resolver.d.ts +11 -0
  128. package/dist/conversations/scope-resolver.js +18 -0
  129. package/dist/conversations/scope-tree.d.ts +10 -0
  130. package/dist/conversations/scope-tree.js +71 -0
  131. package/dist/conversations/transcript-projection.d.ts +9 -0
  132. package/dist/conversations/transcript-projection.js +409 -0
  133. package/dist/conversations/transcript-store.d.ts +24 -0
  134. package/dist/conversations/transcript-store.js +27 -0
  135. package/dist/conversations/types.d.ts +224 -0
  136. package/dist/conversations/types.js +12 -0
  137. package/dist/conversations/validation.d.ts +4 -0
  138. package/dist/conversations/validation.js +383 -0
  139. package/dist/conversations/vault-transcript-store.d.ts +22 -0
  140. package/dist/conversations/vault-transcript-store.js +219 -0
  141. package/dist/core/event-queue.d.ts +6 -0
  142. package/dist/core/event-queue.js +39 -0
  143. package/dist/core/types.d.ts +241 -0
  144. package/dist/core/types.js +50 -0
  145. package/dist/history/ai-history-panel.svelte +937 -0
  146. package/dist/history/ai-history-panel.svelte.d.ts +17 -0
  147. package/dist/history/ai-history-view-type.d.ts +1 -0
  148. package/dist/history/ai-history-view-type.js +1 -0
  149. package/dist/history/ai-history-view.d.ts +26 -0
  150. package/dist/history/ai-history-view.js +51 -0
  151. package/dist/history/conversation-history-tree.d.ts +15 -0
  152. package/dist/history/conversation-history-tree.js +71 -0
  153. package/dist/host/agent-workspace.d.ts +6 -0
  154. package/dist/host/agent-workspace.js +16 -0
  155. package/dist/host/create-host-runtimes.d.ts +2 -0
  156. package/dist/host/create-host-runtimes.js +14 -0
  157. package/dist/host/desktop-process-host.d.ts +6 -0
  158. package/dist/host/desktop-process-host.js +74 -0
  159. package/dist/host/host-runtime-availability.d.ts +1 -0
  160. package/dist/host/host-runtime-availability.js +3 -0
  161. package/dist/host/process-host.d.ts +31 -0
  162. package/dist/host/process-host.js +6 -0
  163. package/dist/index.d.ts +69 -0
  164. package/dist/index.js +49 -0
  165. package/dist/jsonl/ai-jsonl-preview.d.ts +27 -0
  166. package/dist/jsonl/ai-jsonl-preview.js +68 -0
  167. package/dist/jsonl/ai-jsonl-view-type.d.ts +1 -0
  168. package/dist/jsonl/ai-jsonl-view-type.js +1 -0
  169. package/dist/jsonl/ai-jsonl-view.d.ts +16 -0
  170. package/dist/jsonl/ai-jsonl-view.js +57 -0
  171. package/dist/jsonl/ai-jsonl-view.svelte +260 -0
  172. package/dist/jsonl/ai-jsonl-view.svelte.d.ts +9 -0
  173. package/dist/memory/candidate-extractor.d.ts +25 -0
  174. package/dist/memory/candidate-extractor.js +191 -0
  175. package/dist/memory/forget-confirmation.d.ts +3 -0
  176. package/dist/memory/forget-confirmation.js +45 -0
  177. package/dist/memory/hashes.d.ts +5 -0
  178. package/dist/memory/hashes.js +37 -0
  179. package/dist/memory/memory-ingestion-coordinator.d.ts +19 -0
  180. package/dist/memory/memory-ingestion-coordinator.js +108 -0
  181. package/dist/memory/memory-record-store.d.ts +62 -0
  182. package/dist/memory/memory-record-store.js +369 -0
  183. package/dist/memory/memory-scheduler.d.ts +21 -0
  184. package/dist/memory/memory-scheduler.js +143 -0
  185. package/dist/memory/memory-tools.d.ts +61 -0
  186. package/dist/memory/memory-tools.js +99 -0
  187. package/dist/memory/native-memory-service.d.ts +72 -0
  188. package/dist/memory/native-memory-service.js +1256 -0
  189. package/dist/memory/paths.d.ts +13 -0
  190. package/dist/memory/paths.js +60 -0
  191. package/dist/memory/runtime-consolidation-provider.d.ts +18 -0
  192. package/dist/memory/runtime-consolidation-provider.js +154 -0
  193. package/dist/memory/types.d.ts +139 -0
  194. package/dist/memory/types.js +1 -0
  195. package/dist/providers/acp-model-provider.d.ts +11 -0
  196. package/dist/providers/acp-model-provider.js +99 -0
  197. package/dist/providers/codex-model-catalog.d.ts +7 -0
  198. package/dist/providers/codex-model-catalog.js +179 -0
  199. package/dist/providers/codex-model-provider.d.ts +12 -0
  200. package/dist/providers/codex-model-provider.js +42 -0
  201. package/dist/providers/model-provider.d.ts +26 -0
  202. package/dist/providers/model-provider.js +26 -0
  203. package/dist/public-components.d.ts +3 -0
  204. package/dist/public-components.js +3 -0
  205. package/dist/registry/runtime-registry.d.ts +11 -0
  206. package/dist/registry/runtime-registry.js +71 -0
  207. package/dist/registry/select-runtime.d.ts +9 -0
  208. package/dist/registry/select-runtime.js +31 -0
  209. package/dist/runtime-adapters.d.ts +16 -0
  210. package/dist/runtime-adapters.js +9 -0
  211. package/dist/runtimes/acp/acp-event-mapper.d.ts +56 -0
  212. package/dist/runtimes/acp/acp-event-mapper.js +237 -0
  213. package/dist/runtimes/acp/acp-runtime.d.ts +46 -0
  214. package/dist/runtimes/acp/acp-runtime.js +165 -0
  215. package/dist/runtimes/acp/desktop-acp-backend.d.ts +16 -0
  216. package/dist/runtimes/acp/desktop-acp-backend.js +243 -0
  217. package/dist/runtimes/codex/app-server-protocol.d.ts +28 -0
  218. package/dist/runtimes/codex/app-server-protocol.js +274 -0
  219. package/dist/runtimes/codex/codex-runtime.d.ts +24 -0
  220. package/dist/runtimes/codex/codex-runtime.js +318 -0
  221. package/dist/runtimes/fake/fake-runtime.d.ts +51 -0
  222. package/dist/runtimes/fake/fake-runtime.js +257 -0
  223. package/dist/sessions/plugin-data.d.ts +8 -0
  224. package/dist/sessions/plugin-data.js +29 -0
  225. package/dist/sessions/session-store.d.ts +47 -0
  226. package/dist/sessions/session-store.js +117 -0
  227. package/dist/settings/acp-agents.d.ts +8 -0
  228. package/dist/settings/acp-agents.js +11 -0
  229. package/dist/settings/ai-settings-tab.d.ts +8 -0
  230. package/dist/settings/ai-settings-tab.js +249 -0
  231. package/dist/settings/ai-settings.d.ts +43 -0
  232. package/dist/settings/ai-settings.js +147 -0
  233. package/dist/settings/app-tool-setting-rows.d.ts +16 -0
  234. package/dist/settings/app-tool-setting-rows.js +30 -0
  235. package/dist/settings/register-ai-settings.d.ts +3 -0
  236. package/dist/settings/register-ai-settings.js +393 -0
  237. package/dist/skills/activation.d.ts +2 -0
  238. package/dist/skills/activation.js +20 -0
  239. package/dist/skills/bundled/lapis-notes.d.ts +3 -0
  240. package/dist/skills/bundled/lapis-notes.js +52 -0
  241. package/dist/skills/bundled/research.d.ts +6 -0
  242. package/dist/skills/bundled/research.js +29 -0
  243. package/dist/skills/discovery.d.ts +21 -0
  244. package/dist/skills/discovery.js +227 -0
  245. package/dist/skills/manifest.d.ts +3 -0
  246. package/dist/skills/manifest.js +39 -0
  247. package/dist/skills/parser.d.ts +12 -0
  248. package/dist/skills/parser.js +124 -0
  249. package/dist/skills/registry.d.ts +21 -0
  250. package/dist/skills/registry.js +89 -0
  251. package/dist/skills/seed.d.ts +5 -0
  252. package/dist/skills/seed.js +18 -0
  253. package/dist/skills/skill-tools.d.ts +8 -0
  254. package/dist/skills/skill-tools.js +113 -0
  255. package/dist/skills/types.d.ts +67 -0
  256. package/dist/skills/types.js +1 -0
  257. package/dist/styles.css +514 -0
  258. package/dist/tools/app-tool-host.d.ts +47 -0
  259. package/dist/tools/app-tool-host.js +419 -0
  260. package/dist/tools/desktop-app-tool-bridge.d.ts +23 -0
  261. package/dist/tools/desktop-app-tool-bridge.js +223 -0
  262. package/dist/tools/mcp-server-registry.d.ts +7 -0
  263. package/dist/tools/mcp-server-registry.js +30 -0
  264. package/manifest.json +34 -0
  265. package/package.json +83 -0
  266. package/styles.css +1 -0
@@ -0,0 +1,27 @@
1
+ export function conversationStorageKey(location) {
2
+ return `${location.scopeDir}\u0000${location.conversationId}`;
3
+ }
4
+ export function cloneConversationSnapshot(snapshot) {
5
+ return structuredClone(snapshot);
6
+ }
7
+ export class ConversationWriteQueue {
8
+ pending = new Map();
9
+ async run(key, operation) {
10
+ const previous = this.pending.get(key) ?? Promise.resolve();
11
+ let release;
12
+ const gate = new Promise((resolve) => {
13
+ release = resolve;
14
+ });
15
+ const queued = previous.catch(() => undefined).then(() => gate);
16
+ this.pending.set(key, queued);
17
+ await previous.catch(() => undefined);
18
+ try {
19
+ return await operation();
20
+ }
21
+ finally {
22
+ release();
23
+ if (this.pending.get(key) === queued)
24
+ this.pending.delete(key);
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,224 @@
1
+ import type { AgentUsage, AiThinkingLevel, ApprovalKind, ApprovalOption, ModelRef, UserInputQuestion } from "../core/types";
2
+ export declare const CONVERSATION_SCHEMA_VERSION: 3;
3
+ export declare const PREVIOUS_CONVERSATION_SCHEMA_VERSION: 2;
4
+ export declare const LEGACY_CONVERSATION_SCHEMA_VERSION: 1;
5
+ export type ConversationSchemaVersion = typeof LEGACY_CONVERSATION_SCHEMA_VERSION | typeof PREVIOUS_CONVERSATION_SCHEMA_VERSION | typeof CONVERSATION_SCHEMA_VERSION;
6
+ export declare const CONVERSATION_ID_PATTERN: RegExp;
7
+ export type ConversationLocation = {
8
+ scopeDir: string;
9
+ conversationId: string;
10
+ };
11
+ export type ConversationApprovalDecision = "allow-always" | "deny-always";
12
+ export type ConversationApprovalGrant = {
13
+ name: string;
14
+ decision: ConversationApprovalDecision;
15
+ };
16
+ export type ConversationMetadata = {
17
+ schemaVersion: ConversationSchemaVersion;
18
+ id: string;
19
+ title?: string;
20
+ createdAt: string;
21
+ updatedAt: string;
22
+ launchContext?: {
23
+ notePath?: string;
24
+ };
25
+ workspace?: {
26
+ path: string;
27
+ };
28
+ activeAgentBindingId?: string;
29
+ approvalGrants?: ConversationApprovalGrant[];
30
+ pinned?: boolean;
31
+ status: "active" | "archived";
32
+ };
33
+ export type AgentBindingCreatedRecord = {
34
+ schemaVersion: ConversationSchemaVersion;
35
+ type: "binding.created";
36
+ id: string;
37
+ createdAt: string;
38
+ runtime: string;
39
+ agent?: string;
40
+ model?: ModelRef;
41
+ thinking?: AiThinkingLevel;
42
+ nativeSessionId?: string;
43
+ executionHostId?: string;
44
+ handoffThroughEntryId?: string;
45
+ replacesBindingId?: string;
46
+ };
47
+ export type AgentUsageRecord = {
48
+ schemaVersion: ConversationSchemaVersion;
49
+ type: "usage.updated";
50
+ id: string;
51
+ createdAt: string;
52
+ agentBindingId: string;
53
+ turnId?: string;
54
+ usage: AgentUsage;
55
+ };
56
+ export type HandoffProjectionMode = "full" | "delta" | "summary-tail";
57
+ export type AgentBindingContextUpdatedRecord = {
58
+ schemaVersion: ConversationSchemaVersion;
59
+ type: "binding.context.updated";
60
+ id: string;
61
+ createdAt: string;
62
+ agentBindingId: string;
63
+ throughEntryId: string;
64
+ throughEntryHash: string;
65
+ cause: "native-turn" | "handoff";
66
+ handoffId?: string;
67
+ projectionMode?: HandoffProjectionMode;
68
+ omittedEntryCount?: number;
69
+ };
70
+ export type AgentBindingConfigUpdatedRecord = {
71
+ schemaVersion: ConversationSchemaVersion;
72
+ type: "binding.config.updated";
73
+ id: string;
74
+ createdAt: string;
75
+ agentBindingId: string;
76
+ model?: ModelRef;
77
+ thinking?: AiThinkingLevel;
78
+ };
79
+ export type HandoffSummaryCreatedRecord = {
80
+ schemaVersion: ConversationSchemaVersion;
81
+ type: "handoff.summary.created";
82
+ id: string;
83
+ createdAt: string;
84
+ conversationId: string;
85
+ fromEntryId: string;
86
+ throughEntryId: string;
87
+ sourceHash: string;
88
+ summary: string;
89
+ processor: {
90
+ runtime: string;
91
+ agent?: string;
92
+ model?: string;
93
+ };
94
+ estimatedTokens: number;
95
+ };
96
+ export type AgentBindingRecord = AgentBindingCreatedRecord | AgentUsageRecord | AgentBindingContextUpdatedRecord | AgentBindingConfigUpdatedRecord | HandoffSummaryCreatedRecord;
97
+ export type RuntimeEventProvenance = {
98
+ sessionId: string;
99
+ runId: string;
100
+ sequence: number;
101
+ };
102
+ type TranscriptEntryBase = {
103
+ schemaVersion: ConversationSchemaVersion;
104
+ id: string;
105
+ createdAt: string;
106
+ parentId?: string;
107
+ agentBindingId?: string;
108
+ source?: RuntimeEventProvenance;
109
+ provenance?: {
110
+ originClass: "owner" | "agent" | "untrusted" | "system";
111
+ sourceKind: "user-message" | "assistant-message" | "runtime-output" | "owner-response" | "app-system";
112
+ };
113
+ };
114
+ export type TranscriptEntry = (TranscriptEntryBase & {
115
+ type: "message";
116
+ role: "user" | "assistant";
117
+ text: string;
118
+ }) | (TranscriptEntryBase & {
119
+ type: "thinking.summary";
120
+ text: string;
121
+ kind?: "summary" | "plan";
122
+ }) | (TranscriptEntryBase & {
123
+ type: "tool";
124
+ toolId: string;
125
+ name: string;
126
+ server?: string;
127
+ state: "completed" | "error" | "cancelled";
128
+ input?: string;
129
+ output?: string;
130
+ redacted?: boolean;
131
+ truncated?: boolean;
132
+ }) | (TranscriptEntryBase & {
133
+ type: "approval.request";
134
+ requestId: string;
135
+ kind: ApprovalKind;
136
+ title: string;
137
+ tool?: {
138
+ name: string;
139
+ input?: string;
140
+ };
141
+ options: ApprovalOption[];
142
+ redacted?: boolean;
143
+ truncated?: boolean;
144
+ }) | (TranscriptEntryBase & {
145
+ type: "approval.response";
146
+ requestId: string;
147
+ option: {
148
+ id: string;
149
+ label: string;
150
+ };
151
+ }) | (TranscriptEntryBase & {
152
+ type: "question.request";
153
+ requestId: string;
154
+ title: string;
155
+ questions: UserInputQuestion[];
156
+ }) | (TranscriptEntryBase & {
157
+ type: "question.response";
158
+ requestId: string;
159
+ status: "answered" | "cancelled";
160
+ }) | (TranscriptEntryBase & {
161
+ type: "agent.switch";
162
+ fromBindingId?: string;
163
+ toBindingId: string;
164
+ handoffId?: string;
165
+ handoffMode?: HandoffProjectionMode;
166
+ handoffThroughEntryId?: string;
167
+ omittedEntryCount?: number;
168
+ }) | (TranscriptEntryBase & {
169
+ type: "agent.config";
170
+ model?: ModelRef;
171
+ thinking?: AiThinkingLevel;
172
+ }) | (TranscriptEntryBase & {
173
+ type: "system.notice";
174
+ text: string;
175
+ layout?: "report" | "inventory";
176
+ inventory?: {
177
+ kind: "skills" | "tools";
178
+ items: Array<{
179
+ name: string;
180
+ description?: string;
181
+ path?: string;
182
+ kind: "skill" | "tool";
183
+ }>;
184
+ };
185
+ }) | (TranscriptEntryBase & {
186
+ type: "cancelled";
187
+ text?: string;
188
+ requestId?: string;
189
+ interactionType?: "approval" | "question";
190
+ }) | (TranscriptEntryBase & {
191
+ type: "error";
192
+ message: string;
193
+ retryable?: boolean;
194
+ }) | (TranscriptEntryBase & {
195
+ type: "command";
196
+ command: string;
197
+ origin: "app" | "extension" | "skill" | "native-agent";
198
+ arguments?: string;
199
+ status: "completed" | "failed" | "cancelled";
200
+ }) | (TranscriptEntryBase & {
201
+ type: "skill-activation";
202
+ skillId: string;
203
+ skillName: string;
204
+ version: string;
205
+ origin: "user" | "model" | "app";
206
+ arguments?: string;
207
+ });
208
+ export type ConversationReadWarning = {
209
+ file: "agents.jsonl" | "transcript.jsonl";
210
+ line: number;
211
+ message: string;
212
+ };
213
+ export type ConversationSnapshot = {
214
+ location: ConversationLocation;
215
+ metadata: ConversationMetadata;
216
+ agents: AgentBindingRecord[];
217
+ transcript: TranscriptEntry[];
218
+ warnings: ConversationReadWarning[];
219
+ };
220
+ export declare class ConversationUnavailableError extends Error {
221
+ readonly location: ConversationLocation;
222
+ constructor(location: ConversationLocation, message: string, options?: ErrorOptions);
223
+ }
224
+ export {};
@@ -0,0 +1,12 @@
1
+ export const CONVERSATION_SCHEMA_VERSION = 3;
2
+ export const PREVIOUS_CONVERSATION_SCHEMA_VERSION = 2;
3
+ export const LEGACY_CONVERSATION_SCHEMA_VERSION = 1;
4
+ export const CONVERSATION_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u;
5
+ export class ConversationUnavailableError extends Error {
6
+ location;
7
+ constructor(location, message, options) {
8
+ super(message, options);
9
+ this.location = location;
10
+ this.name = "ConversationUnavailableError";
11
+ }
12
+ }
@@ -0,0 +1,4 @@
1
+ import { type AgentBindingRecord, type ConversationMetadata, type TranscriptEntry } from "./types";
2
+ export declare function validateConversationMetadata(value: unknown): ConversationMetadata;
3
+ export declare function validateAgentBindingRecord(value: unknown): AgentBindingRecord;
4
+ export declare function validateTranscriptEntry(value: unknown): TranscriptEntry;
@@ -0,0 +1,383 @@
1
+ import { MAX_CONVERSATION_APPROVAL_GRANTS, normalizeApprovalGrants, } from "./approval-grants";
2
+ import { CONVERSATION_SCHEMA_VERSION, LEGACY_CONVERSATION_SCHEMA_VERSION, PREVIOUS_CONVERSATION_SCHEMA_VERSION, } from "./types";
3
+ import { assertConversationId, normalizePortableVaultPath } from "./paths";
4
+ function record(value, label) {
5
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
6
+ throw new Error(`${label} must be an object`);
7
+ }
8
+ return value;
9
+ }
10
+ function requiredString(value, key, label) {
11
+ if (typeof value[key] !== "string" || !value[key]) {
12
+ throw new Error(`${label}.${key} must be a non-empty string`);
13
+ }
14
+ return value[key];
15
+ }
16
+ function assertSchemaVersion(value, label) {
17
+ if (value.schemaVersion !== CONVERSATION_SCHEMA_VERSION &&
18
+ value.schemaVersion !== PREVIOUS_CONVERSATION_SCHEMA_VERSION &&
19
+ value.schemaVersion !== LEGACY_CONVERSATION_SCHEMA_VERSION) {
20
+ throw new Error(`${label} uses an unsupported required schema version`);
21
+ }
22
+ }
23
+ function assertCurrentSchemaVersion(value, label) {
24
+ if (value.schemaVersion !== CONVERSATION_SCHEMA_VERSION) {
25
+ throw new Error(`${label} requires schema version 3`);
26
+ }
27
+ }
28
+ function assertModelRef(value, label) {
29
+ if (value == null)
30
+ return;
31
+ const model = record(value, label);
32
+ requiredString(model, "provider", label);
33
+ requiredString(model, "model", label);
34
+ }
35
+ function assertTimestamp(value, key, label) {
36
+ const timestamp = requiredString(value, key, label);
37
+ if (!Number.isFinite(Date.parse(timestamp))) {
38
+ throw new Error(`${label}.${key} must be an ISO timestamp`);
39
+ }
40
+ }
41
+ function assertOptionalString(value, key, label) {
42
+ if (value[key] != null && typeof value[key] !== "string") {
43
+ throw new Error(`${label}.${key} must be a string`);
44
+ }
45
+ }
46
+ function assertInventory(value, label) {
47
+ const inventory = record(value, `${label}.inventory`);
48
+ if (inventory.kind !== "skills" && inventory.kind !== "tools") {
49
+ throw new Error(`${label}.inventory.kind is invalid`);
50
+ }
51
+ if (!Array.isArray(inventory.items)) {
52
+ throw new Error(`${label}.inventory.items must be an array`);
53
+ }
54
+ for (const entry of inventory.items) {
55
+ const item = record(entry, `${label}.inventory.item`);
56
+ requiredString(item, "name", `${label}.inventory.item`);
57
+ if (item.kind !== "skill" && item.kind !== "tool") {
58
+ throw new Error(`${label}.inventory.item.kind is invalid`);
59
+ }
60
+ assertOptionalString(item, "description", `${label}.inventory.item`);
61
+ assertOptionalString(item, "path", `${label}.inventory.item`);
62
+ }
63
+ }
64
+ function assertPortableOptionalPath(value, label) {
65
+ if (value == null)
66
+ return;
67
+ if (typeof value !== "string")
68
+ throw new Error(`${label} must be a string`);
69
+ normalizePortableVaultPath(value, { allowRoot: true, label });
70
+ }
71
+ export function validateConversationMetadata(value) {
72
+ const data = record(value, "Conversation metadata");
73
+ assertSchemaVersion(data, "Conversation metadata");
74
+ assertConversationId(requiredString(data, "id", "Conversation metadata"));
75
+ assertTimestamp(data, "createdAt", "Conversation metadata");
76
+ assertTimestamp(data, "updatedAt", "Conversation metadata");
77
+ if (data.status !== "active" && data.status !== "archived") {
78
+ throw new Error("Conversation metadata.status is invalid");
79
+ }
80
+ if (data.title != null && typeof data.title !== "string") {
81
+ throw new Error("Conversation metadata.title must be a string");
82
+ }
83
+ if (typeof data.title === "string" &&
84
+ (/\r|\n/u.test(data.title) || [...data.title].length > 80)) {
85
+ throw new Error("Conversation metadata.title must be one line of at most 80 code points");
86
+ }
87
+ assertOptionalString(data, "activeAgentBindingId", "Conversation metadata");
88
+ if (data.launchContext != null) {
89
+ const launch = record(data.launchContext, "Conversation launchContext");
90
+ assertPortableOptionalPath(launch.notePath, "Conversation launchContext.notePath");
91
+ }
92
+ if (data.workspace != null) {
93
+ const workspace = record(data.workspace, "Conversation workspace");
94
+ requiredString(workspace, "path", "Conversation workspace");
95
+ assertPortableOptionalPath(workspace.path, "Conversation workspace.path");
96
+ }
97
+ if (data.approvalGrants != null) {
98
+ if (!Array.isArray(data.approvalGrants)) {
99
+ throw new Error("Conversation metadata.approvalGrants must be an array");
100
+ }
101
+ if (data.approvalGrants.length > MAX_CONVERSATION_APPROVAL_GRANTS) {
102
+ throw new Error("Conversation metadata.approvalGrants exceeds the stored limit");
103
+ }
104
+ const grants = normalizeApprovalGrants(data.approvalGrants);
105
+ if (grants.length > 0)
106
+ data.approvalGrants = grants;
107
+ else
108
+ delete data.approvalGrants;
109
+ }
110
+ if (data.pinned != null && typeof data.pinned !== "boolean") {
111
+ throw new Error("Conversation metadata.pinned must be a boolean");
112
+ }
113
+ if (data.pinned === false)
114
+ delete data.pinned;
115
+ return data;
116
+ }
117
+ export function validateAgentBindingRecord(value) {
118
+ const data = record(value, "Agent record");
119
+ assertSchemaVersion(data, "Agent record");
120
+ requiredString(data, "id", "Agent record");
121
+ assertTimestamp(data, "createdAt", "Agent record");
122
+ if (data.type === "binding.created") {
123
+ requiredString(data, "runtime", "Agent record");
124
+ for (const key of [
125
+ "agent",
126
+ "nativeSessionId",
127
+ "executionHostId",
128
+ "handoffThroughEntryId",
129
+ "replacesBindingId",
130
+ ]) {
131
+ assertOptionalString(data, key, "Agent record");
132
+ }
133
+ }
134
+ else if (data.type === "usage.updated") {
135
+ requiredString(data, "agentBindingId", "Agent record");
136
+ const usage = record(data.usage, "Agent record usage");
137
+ if (typeof usage.used !== "number" ||
138
+ typeof usage.limit !== "number" ||
139
+ !Number.isFinite(usage.used) ||
140
+ !Number.isFinite(usage.limit) ||
141
+ usage.used < 0 ||
142
+ usage.limit <= 0) {
143
+ throw new Error("Agent record usage is invalid");
144
+ }
145
+ }
146
+ else if (data.type === "binding.context.updated") {
147
+ assertCurrentSchemaVersion(data, "Agent context record");
148
+ requiredString(data, "agentBindingId", "Agent record");
149
+ requiredString(data, "throughEntryId", "Agent record");
150
+ const hash = requiredString(data, "throughEntryHash", "Agent record");
151
+ if (!/^[0-9a-f]{64}$/u.test(hash)) {
152
+ throw new Error("Agent record.throughEntryHash is invalid");
153
+ }
154
+ if (data.cause !== "native-turn" && data.cause !== "handoff") {
155
+ throw new Error("Agent record.cause is invalid");
156
+ }
157
+ assertOptionalString(data, "handoffId", "Agent record");
158
+ assertProjectionMode(data.projectionMode, "Agent record.projectionMode");
159
+ assertOptionalCount(data.omittedEntryCount, "Agent record.omittedEntryCount");
160
+ }
161
+ else if (data.type === "binding.config.updated") {
162
+ assertCurrentSchemaVersion(data, "Agent configuration record");
163
+ requiredString(data, "agentBindingId", "Agent record");
164
+ assertModelRef(data.model, "Agent record.model");
165
+ assertThinking(data.thinking, "Agent record.thinking");
166
+ if (data.model == null && data.thinking == null) {
167
+ throw new Error("Agent configuration record must change a field");
168
+ }
169
+ }
170
+ else if (data.type === "handoff.summary.created") {
171
+ assertCurrentSchemaVersion(data, "Handoff summary record");
172
+ requiredString(data, "conversationId", "Agent record");
173
+ requiredString(data, "fromEntryId", "Agent record");
174
+ requiredString(data, "throughEntryId", "Agent record");
175
+ const hash = requiredString(data, "sourceHash", "Agent record");
176
+ if (!/^[0-9a-f]{64}$/u.test(hash)) {
177
+ throw new Error("Agent record.sourceHash is invalid");
178
+ }
179
+ requiredString(data, "summary", "Agent record");
180
+ const processor = record(data.processor, "Agent record processor");
181
+ requiredString(processor, "runtime", "Agent record processor");
182
+ requiredString(processor, "agent", "Agent record processor");
183
+ requiredString(processor, "model", "Agent record processor");
184
+ if (!Number.isSafeInteger(data.estimatedTokens) ||
185
+ Number(data.estimatedTokens) <= 0) {
186
+ throw new Error("Agent record.estimatedTokens is invalid");
187
+ }
188
+ }
189
+ else {
190
+ throw new Error("Agent record type is unsupported");
191
+ }
192
+ return data;
193
+ }
194
+ export function validateTranscriptEntry(value) {
195
+ const data = record(value, "Transcript entry");
196
+ assertSchemaVersion(data, "Transcript entry");
197
+ requiredString(data, "id", "Transcript entry");
198
+ assertTimestamp(data, "createdAt", "Transcript entry");
199
+ const types = new Set([
200
+ "message",
201
+ "thinking.summary",
202
+ "tool",
203
+ "approval.request",
204
+ "approval.response",
205
+ "question.request",
206
+ "question.response",
207
+ "agent.switch",
208
+ "agent.config",
209
+ "system.notice",
210
+ "cancelled",
211
+ "error",
212
+ "command",
213
+ "skill-activation",
214
+ ]);
215
+ if (typeof data.type !== "string" || !types.has(data.type)) {
216
+ throw new Error("Transcript entry type is unsupported");
217
+ }
218
+ if (data.source != null) {
219
+ const source = record(data.source, "Transcript entry source");
220
+ requiredString(source, "sessionId", "Transcript entry source");
221
+ requiredString(source, "runId", "Transcript entry source");
222
+ if (!Number.isSafeInteger(source.sequence) || Number(source.sequence) < 0) {
223
+ throw new Error("Transcript entry source.sequence is invalid");
224
+ }
225
+ }
226
+ if (data.provenance != null) {
227
+ const provenance = record(data.provenance, "Transcript entry provenance");
228
+ if (!["owner", "agent", "untrusted", "system"].includes(String(provenance.originClass))) {
229
+ throw new Error("Transcript entry provenance.originClass is invalid");
230
+ }
231
+ if (![
232
+ "user-message",
233
+ "assistant-message",
234
+ "runtime-output",
235
+ "owner-response",
236
+ "app-system",
237
+ ].includes(String(provenance.sourceKind))) {
238
+ throw new Error("Transcript entry provenance.sourceKind is invalid");
239
+ }
240
+ }
241
+ switch (data.type) {
242
+ case "message":
243
+ if (data.role !== "user" && data.role !== "assistant") {
244
+ throw new Error("Transcript message role is invalid");
245
+ }
246
+ requiredString(data, "text", "Transcript message");
247
+ break;
248
+ case "thinking.summary":
249
+ requiredString(data, "text", "Transcript thinking summary");
250
+ if (data.kind != null &&
251
+ data.kind !== "summary" &&
252
+ data.kind !== "plan") {
253
+ throw new Error("Transcript thinking summary kind is invalid");
254
+ }
255
+ break;
256
+ case "tool":
257
+ requiredString(data, "toolId", "Transcript tool");
258
+ requiredString(data, "name", "Transcript tool");
259
+ if (data.state !== "completed" &&
260
+ data.state !== "error" &&
261
+ data.state !== "cancelled") {
262
+ throw new Error("Transcript tool state is invalid");
263
+ }
264
+ assertOptionalString(data, "input", "Transcript tool");
265
+ assertOptionalString(data, "output", "Transcript tool");
266
+ break;
267
+ case "approval.request":
268
+ requiredString(data, "requestId", "Transcript approval request");
269
+ requiredString(data, "title", "Transcript approval request");
270
+ if (!Array.isArray(data.options)) {
271
+ throw new Error("Transcript approval request options are invalid");
272
+ }
273
+ if ("metadata" in data) {
274
+ throw new Error("Transcript approval request must not retain metadata");
275
+ }
276
+ break;
277
+ case "approval.response":
278
+ requiredString(data, "requestId", "Transcript approval response");
279
+ if (!data.option || typeof data.option !== "object") {
280
+ throw new Error("Transcript approval response option is invalid");
281
+ }
282
+ break;
283
+ case "question.request":
284
+ requiredString(data, "requestId", "Transcript question request");
285
+ requiredString(data, "title", "Transcript question request");
286
+ if (!Array.isArray(data.questions) || "answers" in data) {
287
+ throw new Error("Transcript question request is invalid");
288
+ }
289
+ break;
290
+ case "question.response":
291
+ requiredString(data, "requestId", "Transcript question response");
292
+ if ((data.status !== "answered" && data.status !== "cancelled") ||
293
+ "answers" in data) {
294
+ throw new Error("Transcript question response is invalid");
295
+ }
296
+ break;
297
+ case "agent.switch":
298
+ requiredString(data, "toBindingId", "Transcript agent switch");
299
+ assertOptionalString(data, "handoffId", "Transcript agent switch");
300
+ assertOptionalString(data, "handoffThroughEntryId", "Transcript agent switch");
301
+ assertProjectionMode(data.handoffMode, "Transcript agent switch handoffMode");
302
+ assertOptionalCount(data.omittedEntryCount, "Transcript agent switch omittedEntryCount");
303
+ break;
304
+ case "agent.config":
305
+ assertCurrentSchemaVersion(data, "Transcript agent config");
306
+ assertModelRef(data.model, "Transcript agent config model");
307
+ assertThinking(data.thinking, "Transcript agent config thinking");
308
+ if (data.model == null && data.thinking == null) {
309
+ throw new Error("Transcript agent config must change a field");
310
+ }
311
+ break;
312
+ case "system.notice":
313
+ requiredString(data, "text", "Transcript system notice");
314
+ if (data.layout != null &&
315
+ data.layout !== "report" &&
316
+ data.layout !== "inventory") {
317
+ throw new Error("Transcript system notice layout is invalid");
318
+ }
319
+ if (data.layout === "inventory") {
320
+ assertInventory(data.inventory, "Transcript system notice");
321
+ }
322
+ break;
323
+ case "cancelled":
324
+ assertOptionalString(data, "text", "Transcript cancellation");
325
+ assertOptionalString(data, "requestId", "Transcript cancellation");
326
+ if (data.interactionType != null &&
327
+ data.interactionType !== "approval" &&
328
+ data.interactionType !== "question") {
329
+ throw new Error("Transcript cancellation interaction type is invalid");
330
+ }
331
+ break;
332
+ case "error":
333
+ requiredString(data, "message", "Transcript error");
334
+ break;
335
+ case "command":
336
+ requiredString(data, "command", "Transcript command");
337
+ if (data.origin !== "app" &&
338
+ data.origin !== "extension" &&
339
+ data.origin !== "skill" &&
340
+ data.origin !== "native-agent") {
341
+ throw new Error("Transcript command origin is invalid");
342
+ }
343
+ if (data.status !== "completed" &&
344
+ data.status !== "failed" &&
345
+ data.status !== "cancelled") {
346
+ throw new Error("Transcript command status is invalid");
347
+ }
348
+ break;
349
+ case "skill-activation":
350
+ requiredString(data, "skillId", "Transcript skill activation");
351
+ requiredString(data, "skillName", "Transcript skill activation");
352
+ requiredString(data, "version", "Transcript skill activation");
353
+ if (data.origin !== "user" &&
354
+ data.origin !== "model" &&
355
+ data.origin !== "app") {
356
+ throw new Error("Transcript skill activation origin is invalid");
357
+ }
358
+ break;
359
+ }
360
+ return data;
361
+ }
362
+ function assertProjectionMode(value, label) {
363
+ if (value != null &&
364
+ value !== "full" &&
365
+ value !== "delta" &&
366
+ value !== "summary-tail") {
367
+ throw new Error(`${label} is invalid`);
368
+ }
369
+ }
370
+ function assertOptionalCount(value, label) {
371
+ if (value != null && (!Number.isSafeInteger(value) || Number(value) < 0)) {
372
+ throw new Error(`${label} is invalid`);
373
+ }
374
+ }
375
+ function assertThinking(value, label) {
376
+ if (value != null &&
377
+ value !== "off" &&
378
+ value !== "low" &&
379
+ value !== "medium" &&
380
+ value !== "high") {
381
+ throw new Error(`${label} is invalid`);
382
+ }
383
+ }
@@ -0,0 +1,22 @@
1
+ import { type Vault } from "@lapis-notes/api/vault";
2
+ import { type ConversationListEntry, type TranscriptStore } from "./transcript-store";
3
+ import { type AgentBindingRecord, type ConversationLocation, type ConversationMetadata, type ConversationSnapshot, type TranscriptEntry } from "./types";
4
+ declare const MAX_METADATA_BYTES: number;
5
+ export declare class VaultTranscriptStore implements TranscriptStore {
6
+ private readonly vault;
7
+ private readonly queue;
8
+ constructor(vault: Vault);
9
+ create(location: ConversationLocation, metadata: ConversationMetadata): Promise<ConversationSnapshot>;
10
+ read(location: ConversationLocation): Promise<ConversationSnapshot>;
11
+ list(scopeDir: string): Promise<ConversationListEntry[]>;
12
+ listAll(): Promise<ConversationListEntry[]>;
13
+ writeMetadata(location: ConversationLocation, metadata: ConversationMetadata): Promise<void>;
14
+ appendAgentRecords(location: ConversationLocation, records: AgentBindingRecord[]): Promise<void>;
15
+ appendTranscriptEntries(location: ConversationLocation, entries: TranscriptEntry[]): Promise<void>;
16
+ delete(location: ConversationLocation): Promise<void>;
17
+ private metadataYaml;
18
+ private readRequired;
19
+ private replaceText;
20
+ private appendText;
21
+ }
22
+ export { MAX_METADATA_BYTES };