@duetso/agent 0.2.6 → 0.3.1

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 (221) hide show
  1. package/README.md +29 -16
  2. package/dist/package.json +8 -3
  3. package/dist/src/cli/auto-upgrade.d.ts.map +1 -1
  4. package/dist/src/cli/auto-upgrade.js +7 -54
  5. package/dist/src/cli/auto-upgrade.js.map +1 -1
  6. package/dist/src/cli/connect.d.ts +45 -0
  7. package/dist/src/cli/connect.d.ts.map +1 -0
  8. package/dist/src/cli/connect.js +265 -0
  9. package/dist/src/cli/connect.js.map +1 -0
  10. package/dist/src/cli/help.d.ts +1 -0
  11. package/dist/src/cli/help.d.ts.map +1 -1
  12. package/dist/src/cli/help.js +66 -32
  13. package/dist/src/cli/help.js.map +1 -1
  14. package/dist/src/cli/memory-add.d.ts +18 -13
  15. package/dist/src/cli/memory-add.d.ts.map +1 -1
  16. package/dist/src/cli/memory-add.js +91 -32
  17. package/dist/src/cli/memory-add.js.map +1 -1
  18. package/dist/src/cli/memory-recall.d.ts.map +1 -1
  19. package/dist/src/cli/memory-recall.js +3 -0
  20. package/dist/src/cli/memory-recall.js.map +1 -1
  21. package/dist/src/cli/memory-sources.d.ts +20 -0
  22. package/dist/src/cli/memory-sources.d.ts.map +1 -0
  23. package/dist/src/cli/memory-sources.js +40 -0
  24. package/dist/src/cli/memory-sources.js.map +1 -0
  25. package/dist/src/cli/model.d.ts +5 -0
  26. package/dist/src/cli/model.d.ts.map +1 -1
  27. package/dist/src/cli/model.js +43 -0
  28. package/dist/src/cli/model.js.map +1 -1
  29. package/dist/src/cli/route.d.ts +12 -0
  30. package/dist/src/cli/route.d.ts.map +1 -1
  31. package/dist/src/cli/route.js +39 -9
  32. package/dist/src/cli/route.js.map +1 -1
  33. package/dist/src/cli/rpc.d.ts +3 -2
  34. package/dist/src/cli/rpc.d.ts.map +1 -1
  35. package/dist/src/cli/rpc.js +3 -2
  36. package/dist/src/cli/rpc.js.map +1 -1
  37. package/dist/src/cli/run.d.ts +1 -0
  38. package/dist/src/cli/run.d.ts.map +1 -1
  39. package/dist/src/cli/run.js +1 -0
  40. package/dist/src/cli/run.js.map +1 -1
  41. package/dist/src/cli/shared.d.ts +11 -0
  42. package/dist/src/cli/shared.d.ts.map +1 -1
  43. package/dist/src/cli/shared.js +31 -0
  44. package/dist/src/cli/shared.js.map +1 -1
  45. package/dist/src/cli/train.d.ts +31 -7
  46. package/dist/src/cli/train.d.ts.map +1 -1
  47. package/dist/src/cli/train.js +233 -79
  48. package/dist/src/cli/train.js.map +1 -1
  49. package/dist/src/cli.d.ts +3 -1
  50. package/dist/src/cli.d.ts.map +1 -1
  51. package/dist/src/cli.js +9 -1
  52. package/dist/src/cli.js.map +1 -1
  53. package/dist/src/connected-providers/billing.d.ts +6 -0
  54. package/dist/src/connected-providers/billing.d.ts.map +1 -0
  55. package/dist/src/connected-providers/billing.js +11 -0
  56. package/dist/src/connected-providers/billing.js.map +1 -0
  57. package/dist/src/connected-providers/capability-probe.d.ts +17 -0
  58. package/dist/src/connected-providers/capability-probe.d.ts.map +1 -0
  59. package/dist/src/connected-providers/capability-probe.js +92 -0
  60. package/dist/src/connected-providers/capability-probe.js.map +1 -0
  61. package/dist/src/connected-providers/fake-issuer.d.ts +61 -0
  62. package/dist/src/connected-providers/fake-issuer.d.ts.map +1 -0
  63. package/dist/src/connected-providers/fake-issuer.js +161 -0
  64. package/dist/src/connected-providers/fake-issuer.js.map +1 -0
  65. package/dist/src/connected-providers/fallback-notice.d.ts +11 -0
  66. package/dist/src/connected-providers/fallback-notice.d.ts.map +1 -0
  67. package/dist/src/connected-providers/fallback-notice.js +20 -0
  68. package/dist/src/connected-providers/fallback-notice.js.map +1 -0
  69. package/dist/src/connected-providers/fallback.d.ts +11 -0
  70. package/dist/src/connected-providers/fallback.d.ts.map +1 -0
  71. package/dist/src/connected-providers/fallback.js +37 -0
  72. package/dist/src/connected-providers/fallback.js.map +1 -0
  73. package/dist/src/connected-providers/refresh.d.ts +12 -0
  74. package/dist/src/connected-providers/refresh.d.ts.map +1 -0
  75. package/dist/src/connected-providers/refresh.js +72 -0
  76. package/dist/src/connected-providers/refresh.js.map +1 -0
  77. package/dist/src/connected-providers/registry.d.ts +17 -0
  78. package/dist/src/connected-providers/registry.d.ts.map +1 -0
  79. package/dist/src/connected-providers/registry.js +30 -0
  80. package/dist/src/connected-providers/registry.js.map +1 -0
  81. package/dist/src/connected-providers/store.d.ts +41 -0
  82. package/dist/src/connected-providers/store.d.ts.map +1 -0
  83. package/dist/src/connected-providers/store.js +145 -0
  84. package/dist/src/connected-providers/store.js.map +1 -0
  85. package/dist/src/connected-providers/tokens.d.ts +42 -0
  86. package/dist/src/connected-providers/tokens.d.ts.map +1 -0
  87. package/dist/src/connected-providers/tokens.js +148 -0
  88. package/dist/src/connected-providers/tokens.js.map +1 -0
  89. package/dist/src/connected-providers/transport-preference.d.ts +26 -0
  90. package/dist/src/connected-providers/transport-preference.d.ts.map +1 -0
  91. package/dist/src/connected-providers/transport-preference.js +42 -0
  92. package/dist/src/connected-providers/transport-preference.js.map +1 -0
  93. package/dist/src/core/structured-output.d.ts.map +1 -1
  94. package/dist/src/core/structured-output.js +2 -1
  95. package/dist/src/core/structured-output.js.map +1 -1
  96. package/dist/src/file-lock.d.ts +22 -0
  97. package/dist/src/file-lock.d.ts.map +1 -0
  98. package/dist/src/file-lock.js +69 -0
  99. package/dist/src/file-lock.js.map +1 -0
  100. package/dist/src/memory/context-pack.d.ts +5 -0
  101. package/dist/src/memory/context-pack.d.ts.map +1 -1
  102. package/dist/src/memory/context-pack.js +6 -0
  103. package/dist/src/memory/context-pack.js.map +1 -1
  104. package/dist/src/memory/id.d.ts +3 -0
  105. package/dist/src/memory/id.d.ts.map +1 -0
  106. package/dist/src/memory/id.js +6 -0
  107. package/dist/src/memory/id.js.map +1 -0
  108. package/dist/src/memory/observational-prompts.d.ts +2 -0
  109. package/dist/src/memory/observational-prompts.d.ts.map +1 -1
  110. package/dist/src/memory/observational-prompts.js +4 -2
  111. package/dist/src/memory/observational-prompts.js.map +1 -1
  112. package/dist/src/memory/observational.d.ts +22 -0
  113. package/dist/src/memory/observational.d.ts.map +1 -1
  114. package/dist/src/memory/observational.js +65 -22
  115. package/dist/src/memory/observational.js.map +1 -1
  116. package/dist/src/memory/paths.d.ts +9 -0
  117. package/dist/src/memory/paths.d.ts.map +1 -0
  118. package/dist/src/memory/paths.js +11 -0
  119. package/dist/src/memory/paths.js.map +1 -0
  120. package/dist/src/memory/storage.d.ts.map +1 -1
  121. package/dist/src/memory/storage.js +1 -4
  122. package/dist/src/memory/storage.js.map +1 -1
  123. package/dist/src/memory/store/discovery.d.ts +7 -0
  124. package/dist/src/memory/store/discovery.d.ts.map +1 -0
  125. package/dist/src/memory/store/discovery.js +34 -0
  126. package/dist/src/memory/store/discovery.js.map +1 -0
  127. package/dist/src/memory/store/file.d.ts +52 -0
  128. package/dist/src/memory/store/file.d.ts.map +1 -0
  129. package/dist/src/memory/store/file.js +287 -0
  130. package/dist/src/memory/store/file.js.map +1 -0
  131. package/dist/src/memory/store/index.d.ts +5 -0
  132. package/dist/src/memory/store/index.d.ts.map +1 -0
  133. package/dist/src/memory/store/index.js +5 -0
  134. package/dist/src/memory/store/index.js.map +1 -0
  135. package/dist/src/memory/store/pack.d.ts +25 -0
  136. package/dist/src/memory/store/pack.d.ts.map +1 -0
  137. package/dist/src/memory/store/pack.js +71 -0
  138. package/dist/src/memory/store/pack.js.map +1 -0
  139. package/dist/src/memory/store/sources.d.ts +55 -0
  140. package/dist/src/memory/store/sources.d.ts.map +1 -0
  141. package/dist/src/memory/store/sources.js +85 -0
  142. package/dist/src/memory/store/sources.js.map +1 -0
  143. package/dist/src/memory/store/store.d.ts +46 -0
  144. package/dist/src/memory/store/store.d.ts.map +1 -0
  145. package/dist/src/memory/store/store.js +171 -0
  146. package/dist/src/memory/store/store.js.map +1 -0
  147. package/dist/src/memory/store.d.ts +19 -16
  148. package/dist/src/memory/store.d.ts.map +1 -1
  149. package/dist/src/memory/store.js +14 -11
  150. package/dist/src/memory/store.js.map +1 -1
  151. package/dist/src/memory-store.js +554 -0
  152. package/dist/src/model-resolution/catalog.d.ts +24 -10
  153. package/dist/src/model-resolution/catalog.d.ts.map +1 -1
  154. package/dist/src/model-resolution/catalog.js +61 -36
  155. package/dist/src/model-resolution/catalog.js.map +1 -1
  156. package/dist/src/model-resolution/duet-gateway.d.ts +2 -0
  157. package/dist/src/model-resolution/duet-gateway.d.ts.map +1 -1
  158. package/dist/src/model-resolution/duet-gateway.js +57 -4
  159. package/dist/src/model-resolution/duet-gateway.js.map +1 -1
  160. package/dist/src/model-resolution/resolver.d.ts +17 -0
  161. package/dist/src/model-resolution/resolver.d.ts.map +1 -1
  162. package/dist/src/model-resolution/resolver.js +49 -4
  163. package/dist/src/model-resolution/resolver.js.map +1 -1
  164. package/dist/src/model-routing/advisor-context.d.ts +31 -5
  165. package/dist/src/model-routing/advisor-context.d.ts.map +1 -1
  166. package/dist/src/model-routing/advisor-context.js +87 -10
  167. package/dist/src/model-routing/advisor-context.js.map +1 -1
  168. package/dist/src/model-routing/advisor-lifecycle.d.ts +14 -5
  169. package/dist/src/model-routing/advisor-lifecycle.d.ts.map +1 -1
  170. package/dist/src/model-routing/advisor-lifecycle.js +24 -7
  171. package/dist/src/model-routing/advisor-lifecycle.js.map +1 -1
  172. package/dist/src/model-routing/prompts.d.ts.map +1 -1
  173. package/dist/src/model-routing/prompts.js +18 -10
  174. package/dist/src/model-routing/prompts.js.map +1 -1
  175. package/dist/src/model-routing/table.js +18 -18
  176. package/dist/src/model-routing/table.js.map +1 -1
  177. package/dist/src/session/session-manager.d.ts +1 -4
  178. package/dist/src/session/session-manager.d.ts.map +1 -1
  179. package/dist/src/session/session-manager.js +2 -5
  180. package/dist/src/session/session-manager.js.map +1 -1
  181. package/dist/src/session/session.d.ts +2 -2
  182. package/dist/src/session/session.d.ts.map +1 -1
  183. package/dist/src/session/session.js +10 -7
  184. package/dist/src/session/session.js.map +1 -1
  185. package/dist/src/train/archive.d.ts.map +1 -1
  186. package/dist/src/train/archive.js +5 -0
  187. package/dist/src/train/archive.js.map +1 -1
  188. package/dist/src/train/types.d.ts +8 -7
  189. package/dist/src/train/types.d.ts.map +1 -1
  190. package/dist/src/tui/sidebar.d.ts.map +1 -1
  191. package/dist/src/tui/sidebar.js +40 -1
  192. package/dist/src/tui/sidebar.js.map +1 -1
  193. package/dist/src/turn-runner/agent-events.d.ts +2 -0
  194. package/dist/src/turn-runner/agent-events.d.ts.map +1 -1
  195. package/dist/src/turn-runner/agent-events.js +11 -0
  196. package/dist/src/turn-runner/agent-events.js.map +1 -1
  197. package/dist/src/turn-runner/subagent.d.ts +4 -1
  198. package/dist/src/turn-runner/subagent.d.ts.map +1 -1
  199. package/dist/src/turn-runner/subagent.js +11 -3
  200. package/dist/src/turn-runner/subagent.js.map +1 -1
  201. package/dist/src/turn-runner/tools.d.ts +3 -3
  202. package/dist/src/turn-runner/tools.d.ts.map +1 -1
  203. package/dist/src/turn-runner/tools.js +1 -1
  204. package/dist/src/turn-runner/tools.js.map +1 -1
  205. package/dist/src/turn-runner/turn-runner.d.ts +19 -3
  206. package/dist/src/turn-runner/turn-runner.d.ts.map +1 -1
  207. package/dist/src/turn-runner/turn-runner.js +162 -33
  208. package/dist/src/turn-runner/turn-runner.js.map +1 -1
  209. package/dist/src/turn-runner/usage-accounting.d.ts +5 -2
  210. package/dist/src/turn-runner/usage-accounting.d.ts.map +1 -1
  211. package/dist/src/turn-runner/usage-accounting.js +18 -6
  212. package/dist/src/turn-runner/usage-accounting.js.map +1 -1
  213. package/dist/src/turn-runner/wire-shaping.d.ts +3 -1
  214. package/dist/src/turn-runner/wire-shaping.d.ts.map +1 -1
  215. package/dist/src/turn-runner/wire-shaping.js +5 -1
  216. package/dist/src/turn-runner/wire-shaping.js.map +1 -1
  217. package/dist/src/types/config.d.ts +7 -0
  218. package/dist/src/types/config.d.ts.map +1 -1
  219. package/dist/src/types/protocol.d.ts +13 -5
  220. package/dist/src/types/protocol.d.ts.map +1 -1
  221. package/package.json +8 -3
@@ -0,0 +1,554 @@
1
+ // src/memory/store/file.ts
2
+ import { Buffer } from "node:buffer";
3
+ import { basename } from "node:path";
4
+ var MAX_TRAIN_RECORD_CONTENT_BYTES = 10 * 1024 * 1024;
5
+ var SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
6
+ var ID_SEGMENT_PATTERN = /^[A-Za-z0-9_-]+$/;
7
+ var KEY_PATTERN = /^[A-Za-z][A-Za-z0-9]*$/;
8
+ var NUMBER_PATTERN = /^-?(?:0|[1-9]\d*)(?:\.\d+)?$/;
9
+ var KNOWN_KEYS = [
10
+ "version",
11
+ "id",
12
+ "kind",
13
+ "createdAt",
14
+ "headline",
15
+ "model",
16
+ "fileCount",
17
+ "archiveId",
18
+ "priority",
19
+ "source",
20
+ "tags"
21
+ ];
22
+ var KNOWN_KEY_ORDER = new Map(KNOWN_KEYS.map((key, index) => [key, index]));
23
+ var parsedLineEndings = new WeakMap;
24
+ function parseMemoryFile(text) {
25
+ const lineEnding = text.startsWith(`---\r
26
+ `) ? `\r
27
+ ` : text.startsWith(`---
28
+ `) ? `
29
+ ` : undefined;
30
+ if (!lineEnding)
31
+ throw new Error("Memory file must start with a frontmatter delimiter");
32
+ const closingDelimiter = `${lineEnding}---${lineEnding}`;
33
+ const closingIndex = text.indexOf(closingDelimiter, 3 + lineEnding.length);
34
+ if (closingIndex === -1)
35
+ throw new Error("Memory file is missing its closing delimiter");
36
+ const header = text.slice(3 + lineEnding.length, closingIndex);
37
+ const content = text.slice(closingIndex + closingDelimiter.length);
38
+ assertContent(content);
39
+ const values = new Map;
40
+ let lastKnownIndex = -1;
41
+ let sawUnknown = false;
42
+ for (const line of header.split(lineEnding)) {
43
+ const separator = line.indexOf(": ");
44
+ if (separator <= 0)
45
+ throw new Error(`Invalid frontmatter line: ${line}`);
46
+ const key = line.slice(0, separator);
47
+ const rawValue = line.slice(separator + 2);
48
+ if (!KEY_PATTERN.test(key))
49
+ throw new Error(`Invalid frontmatter key: ${key}`);
50
+ if (values.has(key))
51
+ throw new Error(`Duplicate frontmatter key: ${key}`);
52
+ if (key === "sourceFolder") {
53
+ throw new Error("sourceFolder is private archive metadata and cannot enter a memory file");
54
+ }
55
+ const knownIndex = KNOWN_KEY_ORDER.get(key);
56
+ if (knownIndex === undefined) {
57
+ sawUnknown = true;
58
+ } else {
59
+ if (sawUnknown || knownIndex <= lastKnownIndex) {
60
+ throw new Error(`Frontmatter key is out of canonical order: ${key}`);
61
+ }
62
+ lastKnownIndex = knownIndex;
63
+ }
64
+ values.set(key, parseScalar(rawValue));
65
+ }
66
+ const version = requireNumber(values, "version");
67
+ if (version !== 1)
68
+ throw new Error(`Unsupported memory file version: ${version}`);
69
+ const kind = requireString(values, "kind");
70
+ if (kind !== "train" && kind !== "note")
71
+ throw new Error(`Invalid memory kind: ${kind}`);
72
+ const createdAt = requireNumber(values, "createdAt");
73
+ if (!Number.isSafeInteger(createdAt) || createdAt < 0) {
74
+ throw new Error("createdAt must be a non-negative integer");
75
+ }
76
+ const fileCount = optionalNumber(values, "fileCount");
77
+ if (fileCount !== undefined && (!Number.isSafeInteger(fileCount) || fileCount < 0)) {
78
+ throw new Error("fileCount must be a non-negative integer");
79
+ }
80
+ const record = {
81
+ version: 1,
82
+ id: requireIdSegment(values, "id"),
83
+ kind,
84
+ createdAt,
85
+ ...optionalStringProperty(values, "headline"),
86
+ ...optionalStringProperty(values, "model"),
87
+ ...fileCount === undefined ? {} : { fileCount },
88
+ ...optionalIdSegmentProperty(values, "archiveId"),
89
+ ...optionalStringProperty(values, "priority"),
90
+ ...optionalStringProperty(values, "source"),
91
+ ...optionalStringArrayProperty(values, "tags"),
92
+ ...extraProperties(values),
93
+ content
94
+ };
95
+ parsedLineEndings.set(record, lineEnding);
96
+ return record;
97
+ }
98
+ function serializeMemoryFile(record) {
99
+ validateRecord(record);
100
+ const lineEnding = parsedLineEndings.get(record) ?? `
101
+ `;
102
+ const fields = [
103
+ ["version", record.version],
104
+ ["id", record.id],
105
+ ["kind", record.kind],
106
+ ["createdAt", record.createdAt]
107
+ ];
108
+ appendOptional(fields, "headline", record.headline);
109
+ appendOptional(fields, "model", record.model);
110
+ appendOptional(fields, "fileCount", record.fileCount);
111
+ appendOptional(fields, "archiveId", record.archiveId);
112
+ appendOptional(fields, "priority", record.priority);
113
+ appendOptional(fields, "source", record.source);
114
+ appendOptional(fields, "tags", record.tags);
115
+ for (const [key, value] of Object.entries(record.extra ?? {})) {
116
+ if (!KEY_PATTERN.test(key) || KNOWN_KEY_ORDER.has(key) || key === "sourceFolder") {
117
+ throw new Error(`Invalid extra frontmatter key: ${key}`);
118
+ }
119
+ fields.push([key, value]);
120
+ }
121
+ const header = fields.map(([key, value]) => `${key}: ${serializeScalar(value)}`).join(lineEnding);
122
+ return `---${lineEnding}${header}${lineEnding}---${lineEnding}${record.content}`;
123
+ }
124
+ function slugFromFilename(name) {
125
+ if (basename(name) !== name || !name.endsWith(".md")) {
126
+ throw new Error(`Memory filename must be a bare .md filename: ${name}`);
127
+ }
128
+ const slug = name.slice(0, -3);
129
+ if (!SLUG_PATTERN.test(slug))
130
+ throw new Error(`Unsafe memory slug: ${slug}`);
131
+ return slug;
132
+ }
133
+ function parseScalar(rawValue) {
134
+ if (NUMBER_PATTERN.test(rawValue)) {
135
+ const value = Number(rawValue);
136
+ if (Number.isFinite(value) && String(value) === rawValue)
137
+ return value;
138
+ }
139
+ try {
140
+ const value = JSON.parse(rawValue);
141
+ if (typeof value === "string" && JSON.stringify(value) === rawValue)
142
+ return value;
143
+ if (Array.isArray(value) && value.every((item) => typeof item === "string") && `[${value.map((item) => JSON.stringify(item)).join(", ")}]` === rawValue) {
144
+ return value;
145
+ }
146
+ } catch {}
147
+ throw new Error(`Unsupported frontmatter scalar: ${rawValue}`);
148
+ }
149
+ function serializeScalar(value) {
150
+ if (typeof value === "number") {
151
+ if (!Number.isFinite(value) || /[eE]/.test(String(value))) {
152
+ throw new Error(`Frontmatter numbers must be finite decimals: ${value}`);
153
+ }
154
+ return String(value);
155
+ }
156
+ if (typeof value === "string")
157
+ return JSON.stringify(value);
158
+ if (Array.isArray(value) && value.every((item) => typeof item === "string")) {
159
+ return `[${value.map((item) => JSON.stringify(item)).join(", ")}]`;
160
+ }
161
+ throw new Error("Frontmatter values must be strings, numbers, or string arrays");
162
+ }
163
+ function requireNumber(values, key) {
164
+ const value = values.get(key);
165
+ if (typeof value !== "number")
166
+ throw new Error(`Frontmatter ${key} must be a number`);
167
+ return value;
168
+ }
169
+ function optionalNumber(values, key) {
170
+ const value = values.get(key);
171
+ if (value === undefined)
172
+ return;
173
+ if (typeof value !== "number")
174
+ throw new Error(`Frontmatter ${key} must be a number`);
175
+ return value;
176
+ }
177
+ function requireString(values, key) {
178
+ const value = values.get(key);
179
+ if (typeof value !== "string")
180
+ throw new Error(`Frontmatter ${key} must be a string`);
181
+ return value;
182
+ }
183
+ function requireNonBlankString(values, key) {
184
+ const value = requireString(values, key);
185
+ if (value.trim().length === 0)
186
+ throw new Error(`Frontmatter ${key} cannot be blank`);
187
+ return value;
188
+ }
189
+ function requireIdSegment(values, key) {
190
+ return assertIdSegment(key, requireNonBlankString(values, key));
191
+ }
192
+ function optionalIdSegmentProperty(values, key) {
193
+ if (!values.has(key))
194
+ return {};
195
+ return { [key]: requireIdSegment(values, key) };
196
+ }
197
+ function assertIdSegment(key, value) {
198
+ if (!ID_SEGMENT_PATTERN.test(value)) {
199
+ throw new Error(`Frontmatter ${key} must be a safe path segment: ${value}`);
200
+ }
201
+ return value;
202
+ }
203
+ function optionalStringProperty(values, key) {
204
+ if (!values.has(key))
205
+ return {};
206
+ return { [key]: requireNonBlankString(values, key) };
207
+ }
208
+ function optionalStringArrayProperty(values, key) {
209
+ const value = values.get(key);
210
+ if (value === undefined)
211
+ return {};
212
+ if (!Array.isArray(value) || value.some((item) => item.trim().length === 0)) {
213
+ throw new Error(`Frontmatter ${key} must be a string array without blank items`);
214
+ }
215
+ return { tags: value };
216
+ }
217
+ function extraProperties(values) {
218
+ const extra = Object.fromEntries(Array.from(values).filter(([key]) => !KNOWN_KEY_ORDER.has(key)));
219
+ return Object.keys(extra).length === 0 ? {} : { extra };
220
+ }
221
+ function appendOptional(fields, key, value) {
222
+ if (value !== undefined)
223
+ fields.push([key, value]);
224
+ }
225
+ function validateRecord(record) {
226
+ if (record.version !== 1)
227
+ throw new Error(`Unsupported memory file version: ${record.version}`);
228
+ if (record.id.trim().length === 0)
229
+ throw new Error("Frontmatter id cannot be blank");
230
+ assertIdSegment("id", record.id);
231
+ if (record.archiveId !== undefined)
232
+ assertIdSegment("archiveId", record.archiveId);
233
+ if (record.kind !== "train" && record.kind !== "note") {
234
+ throw new Error(`Invalid memory kind: ${String(record.kind)}`);
235
+ }
236
+ if (!Number.isSafeInteger(record.createdAt) || record.createdAt < 0) {
237
+ throw new Error("createdAt must be a non-negative integer");
238
+ }
239
+ if (record.fileCount !== undefined && (!Number.isSafeInteger(record.fileCount) || record.fileCount < 0)) {
240
+ throw new Error("fileCount must be a non-negative integer");
241
+ }
242
+ for (const [key, value] of Object.entries({
243
+ headline: record.headline,
244
+ model: record.model,
245
+ archiveId: record.archiveId,
246
+ priority: record.priority,
247
+ source: record.source
248
+ })) {
249
+ if (value !== undefined && value.trim().length === 0) {
250
+ throw new Error(`Frontmatter ${key} cannot be blank`);
251
+ }
252
+ }
253
+ if (record.tags?.some((tag) => tag.trim().length === 0)) {
254
+ throw new Error("Frontmatter tags cannot contain blank items");
255
+ }
256
+ assertContent(record.content);
257
+ }
258
+ function assertContent(content) {
259
+ if (content.trim().length === 0)
260
+ throw new Error("Memory content cannot be blank");
261
+ const bytes = Buffer.byteLength(content, "utf8");
262
+ if (bytes > MAX_TRAIN_RECORD_CONTENT_BYTES) {
263
+ throw new Error(`Memory content exceeds ${MAX_TRAIN_RECORD_CONTENT_BYTES} UTF-8 bytes`);
264
+ }
265
+ }
266
+ // src/memory/store/discovery.ts
267
+ import { lstat } from "node:fs/promises";
268
+ import { join } from "node:path";
269
+
270
+ // src/lib/walk-ancestors.ts
271
+ import { homedir } from "node:os";
272
+ import { dirname, resolve } from "node:path";
273
+ function walkAncestors(cwd, home = homedir()) {
274
+ const resolvedHome = resolve(home);
275
+ const seen = new Set;
276
+ const result = [];
277
+ let current = resolve(cwd);
278
+ while (true) {
279
+ if (seen.has(current))
280
+ break;
281
+ seen.add(current);
282
+ if (current !== resolvedHome)
283
+ result.push(current);
284
+ const parent = dirname(current);
285
+ if (parent === current)
286
+ break;
287
+ current = parent;
288
+ }
289
+ return result;
290
+ }
291
+
292
+ // src/memory/store/discovery.ts
293
+ var MEMORY_ROOT_NAMES = [".duet", ".agents", ".claude"];
294
+ async function discoverMemoryStores(cwd) {
295
+ const stores = [];
296
+ for (const ancestor of walkAncestors(cwd)) {
297
+ for (const rootName of MEMORY_ROOT_NAMES) {
298
+ const storeDir = join(ancestor, rootName, "memories");
299
+ const status = await lstat(storeDir).catch((error) => {
300
+ if (isNodeError(error, "ENOENT") || isNodeError(error, "ENOTDIR"))
301
+ return;
302
+ throw error;
303
+ });
304
+ if (!status)
305
+ continue;
306
+ if (status.isSymbolicLink())
307
+ throw new Error(`Memory stores cannot be symlinks: ${storeDir}`);
308
+ if (!status.isDirectory())
309
+ throw new Error(`Memory store is not a directory: ${storeDir}`);
310
+ stores.push(storeDir);
311
+ }
312
+ }
313
+ return stores;
314
+ }
315
+ function isNodeError(error, code) {
316
+ return error instanceof Error && "code" in error && error.code === code;
317
+ }
318
+ // src/memory/store/sources.ts
319
+ import * as fileSystem from "node:fs/promises";
320
+ import { join as join3, resolve as resolve2 } from "node:path";
321
+
322
+ // src/memory/paths.ts
323
+ import { homedir as homedir2 } from "node:os";
324
+ import { join as join2 } from "node:path";
325
+ var DEFAULT_DUET_DIR = ".duet";
326
+ var DEFAULT_DUET_HOME = join2(homedir2(), DEFAULT_DUET_DIR);
327
+ var DEFAULT_SESSION_STORAGE_DIR = join2(DEFAULT_DUET_HOME, "sessions");
328
+ var DEFAULT_MEMORY_DB_PATH = join2(DEFAULT_DUET_HOME, "memory.db");
329
+
330
+ // src/memory/store/sources.ts
331
+ async function resolveSources(flags, cwd) {
332
+ const explicitCount = flags.stores.length + flags.dbs.length;
333
+ if (explicitCount > 0) {
334
+ const stores2 = unique(flags.stores);
335
+ const dbs = unique(flags.dbs);
336
+ const selected = flags.stores[0] ?? flags.dbs[0];
337
+ const writeTarget = explicitCount === 1 && selected ? { kind: flags.stores.length === 1 ? "store" : "db", path: selected } : undefined;
338
+ return {
339
+ stores: stores2,
340
+ dbs,
341
+ ...writeTarget ? { writeTarget } : {}
342
+ };
343
+ }
344
+ const stores = await discoverMemoryStores(cwd);
345
+ return {
346
+ stores,
347
+ dbs: [DEFAULT_MEMORY_DB_PATH],
348
+ writeTarget: { kind: "store", path: await nearestAgentMemoryStore(cwd) }
349
+ };
350
+ }
351
+ function mergeListings(storeEntries, dbEntries) {
352
+ const winners = new Map;
353
+ for (const listing of storeEntries) {
354
+ for (const entry of listing.entries) {
355
+ if (!winners.has(entry.slug))
356
+ winners.set(entry.slug, { ...entry, store: listing.source });
357
+ }
358
+ }
359
+ for (const listing of dbEntries) {
360
+ for (const entry of listing.entries) {
361
+ if (!winners.has(entry.slug))
362
+ winners.set(entry.slug, { ...entry });
363
+ }
364
+ }
365
+ return Array.from(winners.values()).sort((left, right) => right.createdAt - left.createdAt);
366
+ }
367
+ async function nearestAgentMemoryStore(cwd) {
368
+ for (const ancestor of walkAncestors(cwd)) {
369
+ const agentRoot = join3(ancestor, ".agents");
370
+ const status = await fileSystem.lstat(agentRoot).catch((error) => {
371
+ if (isNodeError2(error, "ENOENT") || isNodeError2(error, "ENOTDIR"))
372
+ return;
373
+ throw error;
374
+ });
375
+ if (!status)
376
+ continue;
377
+ if (status.isSymbolicLink())
378
+ throw new Error(`Agent directories cannot be symlinks: ${agentRoot}`);
379
+ if (!status.isDirectory())
380
+ throw new Error(`Agent path is not a directory: ${agentRoot}`);
381
+ return join3(agentRoot, "memories");
382
+ }
383
+ return join3(resolve2(cwd), ".agents", "memories");
384
+ }
385
+ function unique(paths) {
386
+ return Array.from(new Set(paths));
387
+ }
388
+ function isNodeError2(error, code) {
389
+ return error instanceof Error && "code" in error && error.code === code;
390
+ }
391
+ // src/memory/store/store.ts
392
+ import { randomUUID } from "node:crypto";
393
+ import { constants } from "node:fs";
394
+ import * as fileSystem2 from "node:fs/promises";
395
+ import { basename as basename2, join as join4, resolve as resolve3 } from "node:path";
396
+ async function listStore(dir) {
397
+ return listStoreWithInvalidPolicy(dir);
398
+ }
399
+ async function listStoreWithInvalidPolicy(dir, onInvalidEntry) {
400
+ const storeDir = await requireStoreDirectory(dir, false);
401
+ if (!storeDir)
402
+ return [];
403
+ const directoryEntries = await fileSystem2.readdir(storeDir, { withFileTypes: true });
404
+ const memoryEntries = directoryEntries.filter((entry) => entry.name.endsWith(".md")).sort((left, right) => left.name.localeCompare(right.name));
405
+ const loaded = await Promise.all(memoryEntries.map(async (entry) => {
406
+ const path = join4(storeDir, entry.name);
407
+ try {
408
+ if (entry.isSymbolicLink())
409
+ throw new Error(`Memory files cannot be symlinks: ${entry.name}`);
410
+ if (!entry.isFile())
411
+ throw new Error(`Memory entry is not a regular file: ${entry.name}`);
412
+ return await readEntry(storeDir, slugFromFilename(entry.name));
413
+ } catch (error) {
414
+ if (!onInvalidEntry)
415
+ throw error;
416
+ onInvalidEntry(path, error);
417
+ return;
418
+ }
419
+ }));
420
+ return loaded.filter((entry) => entry !== undefined);
421
+ }
422
+ async function readEntry(dir, slug) {
423
+ const safeSlug = assertSlug(slug);
424
+ const storeDir = await requireStoreDirectory(dir, false);
425
+ if (!storeDir)
426
+ throw new Error(`Memory store does not exist: ${resolve3(dir)}`);
427
+ return (await readParsedEntry(storeDir, safeSlug)).stored;
428
+ }
429
+ async function writeEntry(dir, record) {
430
+ const slug = assertSlug(record.slug);
431
+ const bytes = serializeMemoryFile(record);
432
+ const storeDir = await requireStoreDirectory(dir, true);
433
+ if (!storeDir)
434
+ throw new Error("Memory store could not be created");
435
+ const destination = join4(storeDir, `${slug}.md`);
436
+ await rejectSymlinkIfPresent(destination);
437
+ const temporary = join4(storeDir, `.${slug}.${randomUUID()}.tmp`);
438
+ const handle = await fileSystem2.open(temporary, "wx", 384);
439
+ try {
440
+ try {
441
+ await handle.writeFile(bytes, "utf8");
442
+ await handle.sync();
443
+ } finally {
444
+ await handle.close();
445
+ }
446
+ await fileSystem2.rename(temporary, destination);
447
+ } catch (error) {
448
+ await fileSystem2.rm(temporary, { force: true });
449
+ throw error;
450
+ }
451
+ return toStoredMemory(storeDir, slug, record);
452
+ }
453
+ async function updateEntry(dir, slug, content) {
454
+ const safeSlug = assertSlug(slug);
455
+ const storeDir = await requireStoreDirectory(dir, false);
456
+ if (!storeDir)
457
+ throw new Error(`Memory store does not exist: ${resolve3(dir)}`);
458
+ const { record } = await readParsedEntry(storeDir, safeSlug);
459
+ record.content = content;
460
+ return writeEntry(storeDir, Object.assign(record, { slug: safeSlug }));
461
+ }
462
+ async function deleteEntry(dir, slug) {
463
+ const safeSlug = assertSlug(slug);
464
+ const storeDir = await requireStoreDirectory(dir, false);
465
+ if (!storeDir)
466
+ throw new Error(`Memory store does not exist: ${resolve3(dir)}`);
467
+ const { stored } = await readParsedEntry(storeDir, safeSlug);
468
+ const path = join4(storeDir, `${safeSlug}.md`);
469
+ await rejectSymlinkIfPresent(path);
470
+ await fileSystem2.unlink(path);
471
+ return stored;
472
+ }
473
+ async function readParsedEntry(storeDir, slug) {
474
+ const path = join4(storeDir, `${slug}.md`);
475
+ const status = await fileSystem2.lstat(path);
476
+ if (status.isSymbolicLink())
477
+ throw new Error(`Memory files cannot be symlinks: ${path}`);
478
+ if (!status.isFile())
479
+ throw new Error(`Memory entry is not a regular file: ${path}`);
480
+ const handle = await fileSystem2.open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
481
+ const text = await handle.readFile("utf8").finally(() => handle.close());
482
+ const record = parseMemoryFile(text);
483
+ return { stored: toStoredMemory(storeDir, slug, record), record };
484
+ }
485
+ function toStoredMemory(storeDir, slug, record) {
486
+ return {
487
+ slug,
488
+ storeDir,
489
+ id: record.id,
490
+ kind: record.kind,
491
+ createdAt: record.createdAt,
492
+ ...record.headline === undefined ? {} : { headline: record.headline },
493
+ ...record.model === undefined ? {} : { model: record.model },
494
+ ...record.fileCount === undefined ? {} : { fileCount: record.fileCount },
495
+ ...record.archiveId === undefined ? {} : { archiveId: record.archiveId },
496
+ content: record.content
497
+ };
498
+ }
499
+ function assertSlug(slug) {
500
+ if (basename2(slug) !== slug)
501
+ throw new Error(`Unsafe memory slug: ${slug}`);
502
+ return slugFromFilename(`${slug}.md`);
503
+ }
504
+ async function requireStoreDirectory(dir, create) {
505
+ const storeDir = resolve3(dir);
506
+ const status = await fileSystem2.lstat(storeDir).catch((error) => {
507
+ if (isNodeError3(error, "ENOENT"))
508
+ return;
509
+ throw error;
510
+ });
511
+ if (!status && create) {
512
+ await fileSystem2.mkdir(storeDir, { recursive: true, mode: 448 });
513
+ const createdStatus = await fileSystem2.lstat(storeDir);
514
+ if (!createdStatus.isDirectory() || createdStatus.isSymbolicLink()) {
515
+ throw new Error(`Memory store must be a real directory: ${storeDir}`);
516
+ }
517
+ return storeDir;
518
+ }
519
+ if (!status)
520
+ return;
521
+ if (status.isSymbolicLink())
522
+ throw new Error(`Memory stores cannot be symlinks: ${storeDir}`);
523
+ if (!status.isDirectory())
524
+ throw new Error(`Memory store is not a directory: ${storeDir}`);
525
+ return storeDir;
526
+ }
527
+ async function rejectSymlinkIfPresent(path) {
528
+ const status = await fileSystem2.lstat(path).catch((error) => {
529
+ if (isNodeError3(error, "ENOENT"))
530
+ return;
531
+ throw error;
532
+ });
533
+ if (status?.isSymbolicLink())
534
+ throw new Error(`Memory files cannot be symlinks: ${path}`);
535
+ if (status && !status.isFile())
536
+ throw new Error(`Memory entry is not a regular file: ${path}`);
537
+ }
538
+ function isNodeError3(error, code) {
539
+ return error instanceof Error && "code" in error && error.code === code;
540
+ }
541
+ export {
542
+ writeEntry,
543
+ updateEntry,
544
+ slugFromFilename,
545
+ serializeMemoryFile,
546
+ resolveSources,
547
+ readEntry,
548
+ parseMemoryFile,
549
+ mergeListings,
550
+ listStore,
551
+ discoverMemoryStores,
552
+ deleteEntry,
553
+ MAX_TRAIN_RECORD_CONTENT_BYTES
554
+ };
@@ -1,13 +1,19 @@
1
- export type ProviderName = "duet-gateway" | "vercel-ai-gateway" | "openrouter";
1
+ import type { ConnectedProviderId } from "../connected-providers/store.js";
2
+ /** Metered providers considered by the router when resolving an unpinned model. */
3
+ export type RouterProviderName = "duet-gateway" | "vercel-ai-gateway" | "openrouter";
4
+ /** Any backend capable of carrying a curated catalog model. */
5
+ export type TransportName = RouterProviderName | ConnectedProviderId;
6
+ /** Versionless model families accepted anywhere a curated shorthand is accepted. */
7
+ export type FamilyName = "fable" | "opus" | "sonnet" | "haiku" | "sol" | "terra" | "luna" | "kimi" | "grok" | "deepseek" | "glm";
2
8
  export interface ProviderPreference {
3
9
  /** Provider identifier accepted by pi-ai or handled locally by model resolution. */
4
- provider: ProviderName;
10
+ provider: RouterProviderName;
5
11
  /** Env var override for providers whose credential is not discoverable through pi-ai. */
6
12
  customEnvVar?: () => string | null;
7
13
  }
8
14
  export interface ProviderModelCandidate {
9
15
  /** Provider that supports the candidate model. */
10
- provider: ProviderName;
16
+ provider: RouterProviderName;
11
17
  /** Fully resolved provider:modelId string passed to the runtime model loader. */
12
18
  modelName: string;
13
19
  }
@@ -19,6 +25,10 @@ export declare const DEFAULT_CLI_MEMORY_MODEL = "gpt-5.6-luna";
19
25
  * AI_GATEWAY_API_KEY for the gateway transport.
20
26
  */
21
27
  export declare const PROVIDER_ORDER: readonly ProviderPreference[];
28
+ /** Latest shorthand for each family, derived from the first matching catalog entry. */
29
+ export declare const FAMILY_LATEST: Readonly<Record<FamilyName, string>>;
30
+ /** Resolve a versionless family name to the first versioned shorthand in catalog order. */
31
+ export declare function resolveFamilyShorthand(name: string): string | undefined;
22
32
  export declare function isProviderPinnedModelName(modelName: string): boolean;
23
33
  /**
24
34
  * Clamp a resolved model's output-token ceiling to the catalog's
@@ -30,28 +40,32 @@ export declare function clampModelOutputTokens<T extends {
30
40
  id: string;
31
41
  maxTokens: number;
32
42
  }>(model: T): T;
33
- export declare function getProviderDefaultModel(provider: ProviderName): string;
34
- export declare function getProviderMemoryModel(provider: ProviderName): string;
43
+ export declare function getProviderDefaultModel(provider: RouterProviderName): string;
44
+ export declare function getProviderMemoryModel(provider: RouterProviderName): string;
35
45
  export declare function getModelCandidates(modelName: string): readonly ProviderModelCandidate[];
36
46
  export declare function isKnownShorthand(modelName: string): boolean;
37
47
  export declare function canonicalizeModelName(modelName: string): string;
48
+ /** Resolve a curated shorthand or alias to the id served by a specific transport. */
49
+ export declare function transportModelId(transport: TransportName, shorthand: string): string | undefined;
50
+ /** Recover the curated shorthand represented by a transport-specific model id. */
51
+ export declare function shorthandForTransportModel(transport: TransportName, modelId: string): string | undefined;
38
52
  /**
39
53
  * Normalize a `provider:modelId` model id against catalog aliases so users can
40
54
  * pass familiar variants like `claude-opus-4-7` even when the underlying
41
55
  * provider catalog spells it `claude-opus-4.7`. Falls back to the input id
42
56
  * when no alias matches so unknown ids reach the provider lookup unchanged.
43
57
  */
44
- export declare function canonicalizeProviderModelId(provider: ProviderName, modelId: string): string;
58
+ export declare function canonicalizeProviderModelId(provider: RouterProviderName, modelId: string): string;
45
59
  /**
46
60
  * Map user-friendly provider names (and common aliases) onto the canonical
47
- * `ProviderName`. Returns `undefined` for unknown values so callers can
61
+ * `RouterProviderName`. Returns `undefined` for unknown values so callers can
48
62
  * surface a list of accepted names.
49
63
  */
50
- export declare function resolveProviderShorthand(name: string): ProviderName | undefined;
64
+ export declare function resolveProviderShorthand(name: string): RouterProviderName | undefined;
51
65
  /** Names accepted by `--provider`, in canonical order, for help and errors. */
52
66
  export declare const PROVIDER_SHORTHANDS: readonly string[];
53
67
  /** Build a `provider:modelId` reference for a provider's default chat model. */
54
- export declare function pinnedDefaultModel(provider: ProviderName): string;
68
+ export declare function pinnedDefaultModel(provider: RouterProviderName): string;
55
69
  /** Build a `provider:modelId` reference for a provider's memory model. */
56
- export declare function pinnedMemoryModel(provider: ProviderName): string;
70
+ export declare function pinnedMemoryModel(provider: RouterProviderName): string;
57
71
  //# sourceMappingURL=catalog.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../../src/model-resolution/catalog.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG,mBAAmB,GAAG,YAAY,CAAC;AAE/E,MAAM,WAAW,kBAAkB;IACjC,oFAAoF;IACpF,QAAQ,EAAE,YAAY,CAAC;IACvB,yFAAyF;IACzF,YAAY,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,sBAAsB;IACrC,kDAAkD;IAClD,QAAQ,EAAE,YAAY,CAAC;IACvB,iFAAiF;IACjF,SAAS,EAAE,MAAM,CAAC;CACnB;AAeD,eAAO,MAAM,iBAAiB,aAAa,CAAC;AAC5C,eAAO,MAAM,wBAAwB,iBAAiB,CAAC;AAEvD;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,kBAAkB,EAOvD,CAAC;AAkOF,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAEpE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAQ/F;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAEtE;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAErE;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,sBAAsB,EAAE,CAQvF;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAI3F;AASD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAe/E;AAED,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAAqC,CAAC;AAEvF,gFAAgF;AAChF,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAEjE;AAED,0EAA0E;AAC1E,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAEhE"}
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../../src/model-resolution/catalog.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAE3E,mFAAmF;AACnF,MAAM,MAAM,kBAAkB,GAAG,cAAc,GAAG,mBAAmB,GAAG,YAAY,CAAC;AAErF,+DAA+D;AAC/D,MAAM,MAAM,aAAa,GAAG,kBAAkB,GAAG,mBAAmB,CAAC;AAErE,oFAAoF;AACpF,MAAM,MAAM,UAAU,GAClB,OAAO,GACP,MAAM,GACN,QAAQ,GACR,OAAO,GACP,KAAK,GACL,OAAO,GACP,MAAM,GACN,MAAM,GACN,MAAM,GACN,UAAU,GACV,KAAK,CAAC;AAEV,MAAM,WAAW,kBAAkB;IACjC,oFAAoF;IACpF,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,yFAAyF;IACzF,YAAY,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,sBAAsB;IACrC,kDAAkD;IAClD,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,iFAAiF;IACjF,SAAS,EAAE,MAAM,CAAC;CACnB;AAkBD,eAAO,MAAM,iBAAiB,aAAa,CAAC;AAC5C,eAAO,MAAM,wBAAwB,iBAAiB,CAAC;AAEvD;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,kBAAkB,EAOvD,CAAC;AA2OF,uFAAuF;AACvF,eAAO,MAAM,aAAa,sCAA4D,CAAC;AAEvF,2FAA2F;AAC3F,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEvE;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAEpE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAQ/F;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,CAE5E;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,CAE3E;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,sBAAsB,EAAE,CAQvF;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,qFAAqF;AACrF,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEhG;AAED,kFAAkF;AAClF,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,aAAa,EACxB,OAAO,EAAE,MAAM,GACd,MAAM,GAAG,SAAS,CAGpB;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAIjG;AAYD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAerF;AAED,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAAqC,CAAC;AAEvF,gFAAgF;AAChF,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,CAEvE;AAED,0EAA0E;AAC1E,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,CAEtE"}