@felan-ai/daemon 0.0.0-stage → 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 (288) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +69 -0
  3. package/README.md +61 -2
  4. package/dist/client.d.ts +5 -0
  5. package/dist/client.d.ts.map +1 -0
  6. package/dist/client.js +4 -0
  7. package/dist/client.js.map +1 -0
  8. package/dist/daemon/admission.d.ts +39 -0
  9. package/dist/daemon/admission.d.ts.map +1 -0
  10. package/dist/daemon/admission.js +175 -0
  11. package/dist/daemon/admission.js.map +1 -0
  12. package/dist/daemon/agent-logs.d.ts +11 -0
  13. package/dist/daemon/agent-logs.d.ts.map +1 -0
  14. package/dist/daemon/agent-logs.js +31 -0
  15. package/dist/daemon/agent-logs.js.map +1 -0
  16. package/dist/daemon/bootstrap.d.ts +7 -0
  17. package/dist/daemon/bootstrap.d.ts.map +1 -0
  18. package/dist/daemon/bootstrap.js +4 -0
  19. package/dist/daemon/bootstrap.js.map +1 -0
  20. package/dist/daemon/broker.d.ts +94 -0
  21. package/dist/daemon/broker.d.ts.map +1 -0
  22. package/dist/daemon/broker.js +374 -0
  23. package/dist/daemon/broker.js.map +1 -0
  24. package/dist/daemon/commands.d.ts +47 -0
  25. package/dist/daemon/commands.d.ts.map +1 -0
  26. package/dist/daemon/commands.js +639 -0
  27. package/dist/daemon/commands.js.map +1 -0
  28. package/dist/daemon/control-recovery.d.ts +9 -0
  29. package/dist/daemon/control-recovery.d.ts.map +1 -0
  30. package/dist/daemon/control-recovery.js +68 -0
  31. package/dist/daemon/control-recovery.js.map +1 -0
  32. package/dist/daemon/control-state.d.ts +1915 -0
  33. package/dist/daemon/control-state.d.ts.map +1 -0
  34. package/dist/daemon/control-state.js +154 -0
  35. package/dist/daemon/control-state.js.map +1 -0
  36. package/dist/daemon/control-store.d.ts +113 -0
  37. package/dist/daemon/control-store.d.ts.map +1 -0
  38. package/dist/daemon/control-store.js +901 -0
  39. package/dist/daemon/control-store.js.map +1 -0
  40. package/dist/daemon/execution-policy.d.ts +15 -0
  41. package/dist/daemon/execution-policy.d.ts.map +1 -0
  42. package/dist/daemon/execution-policy.js +42 -0
  43. package/dist/daemon/execution-policy.js.map +1 -0
  44. package/dist/daemon/execution-services.d.ts +5 -0
  45. package/dist/daemon/execution-services.d.ts.map +1 -0
  46. package/dist/daemon/execution-services.js +73 -0
  47. package/dist/daemon/execution-services.js.map +1 -0
  48. package/dist/daemon/executions.d.ts +134 -0
  49. package/dist/daemon/executions.d.ts.map +1 -0
  50. package/dist/daemon/executions.js +486 -0
  51. package/dist/daemon/executions.js.map +1 -0
  52. package/dist/daemon/extension-ui.d.ts +24 -0
  53. package/dist/daemon/extension-ui.d.ts.map +1 -0
  54. package/dist/daemon/extension-ui.js +161 -0
  55. package/dist/daemon/extension-ui.js.map +1 -0
  56. package/dist/daemon/fanout.d.ts +40 -0
  57. package/dist/daemon/fanout.d.ts.map +1 -0
  58. package/dist/daemon/fanout.js +304 -0
  59. package/dist/daemon/fanout.js.map +1 -0
  60. package/dist/daemon/headless-json.d.ts +3 -0
  61. package/dist/daemon/headless-json.d.ts.map +1 -0
  62. package/dist/daemon/headless-json.js +20 -0
  63. package/dist/daemon/headless-json.js.map +1 -0
  64. package/dist/daemon/host-config.d.ts +61 -0
  65. package/dist/daemon/host-config.d.ts.map +1 -0
  66. package/dist/daemon/host-config.js +167 -0
  67. package/dist/daemon/host-config.js.map +1 -0
  68. package/dist/daemon/host-services.d.ts +61 -0
  69. package/dist/daemon/host-services.d.ts.map +1 -0
  70. package/dist/daemon/host-services.js +2 -0
  71. package/dist/daemon/host-services.js.map +1 -0
  72. package/dist/daemon/ipc.d.ts +14 -0
  73. package/dist/daemon/ipc.d.ts.map +1 -0
  74. package/dist/daemon/ipc.js +233 -0
  75. package/dist/daemon/ipc.js.map +1 -0
  76. package/dist/daemon/legacy-sessions.d.ts +48 -0
  77. package/dist/daemon/legacy-sessions.d.ts.map +1 -0
  78. package/dist/daemon/legacy-sessions.js +328 -0
  79. package/dist/daemon/legacy-sessions.js.map +1 -0
  80. package/dist/daemon/lifecycle.d.ts +44 -0
  81. package/dist/daemon/lifecycle.d.ts.map +1 -0
  82. package/dist/daemon/lifecycle.js +164 -0
  83. package/dist/daemon/lifecycle.js.map +1 -0
  84. package/dist/daemon/main.d.ts +3 -0
  85. package/dist/daemon/main.d.ts.map +1 -0
  86. package/dist/daemon/main.js +83 -0
  87. package/dist/daemon/main.js.map +1 -0
  88. package/dist/daemon/message-display.d.ts +4 -0
  89. package/dist/daemon/message-display.d.ts.map +1 -0
  90. package/dist/daemon/message-display.js +20 -0
  91. package/dist/daemon/message-display.js.map +1 -0
  92. package/dist/daemon/native-ownership.d.ts +13 -0
  93. package/dist/daemon/native-ownership.d.ts.map +1 -0
  94. package/dist/daemon/native-ownership.js +173 -0
  95. package/dist/daemon/native-ownership.js.map +1 -0
  96. package/dist/daemon/operational-log.d.ts +23 -0
  97. package/dist/daemon/operational-log.d.ts.map +1 -0
  98. package/dist/daemon/operational-log.js +79 -0
  99. package/dist/daemon/operational-log.js.map +1 -0
  100. package/dist/daemon/ownership.d.ts +35 -0
  101. package/dist/daemon/ownership.d.ts.map +1 -0
  102. package/dist/daemon/ownership.js +395 -0
  103. package/dist/daemon/ownership.js.map +1 -0
  104. package/dist/daemon/persistence.d.ts +110 -0
  105. package/dist/daemon/persistence.d.ts.map +1 -0
  106. package/dist/daemon/persistence.js +540 -0
  107. package/dist/daemon/persistence.js.map +1 -0
  108. package/dist/daemon/process-adapter.d.ts +23 -0
  109. package/dist/daemon/process-adapter.d.ts.map +1 -0
  110. package/dist/daemon/process-adapter.js +2 -0
  111. package/dist/daemon/process-adapter.js.map +1 -0
  112. package/dist/daemon/processes.d.ts +102 -0
  113. package/dist/daemon/processes.d.ts.map +1 -0
  114. package/dist/daemon/processes.js +691 -0
  115. package/dist/daemon/processes.js.map +1 -0
  116. package/dist/daemon/profile-storage.d.ts +16 -0
  117. package/dist/daemon/profile-storage.d.ts.map +1 -0
  118. package/dist/daemon/profile-storage.js +148 -0
  119. package/dist/daemon/profile-storage.js.map +1 -0
  120. package/dist/daemon/projection.d.ts +110 -0
  121. package/dist/daemon/projection.d.ts.map +1 -0
  122. package/dist/daemon/projection.js +661 -0
  123. package/dist/daemon/projection.js.map +1 -0
  124. package/dist/daemon/provider-loader.d.ts +28 -0
  125. package/dist/daemon/provider-loader.d.ts.map +1 -0
  126. package/dist/daemon/provider-loader.js +376 -0
  127. package/dist/daemon/provider-loader.js.map +1 -0
  128. package/dist/daemon/provider.d.ts +92 -0
  129. package/dist/daemon/provider.d.ts.map +1 -0
  130. package/dist/daemon/provider.js +31 -0
  131. package/dist/daemon/provider.js.map +1 -0
  132. package/dist/daemon/registry.d.ts +209 -0
  133. package/dist/daemon/registry.d.ts.map +1 -0
  134. package/dist/daemon/registry.js +1591 -0
  135. package/dist/daemon/registry.js.map +1 -0
  136. package/dist/daemon/runtime-dependencies.d.ts +5 -0
  137. package/dist/daemon/runtime-dependencies.d.ts.map +1 -0
  138. package/dist/daemon/runtime-dependencies.js +31 -0
  139. package/dist/daemon/runtime-dependencies.js.map +1 -0
  140. package/dist/daemon/server.d.ts +110 -0
  141. package/dist/daemon/server.d.ts.map +1 -0
  142. package/dist/daemon/server.js +556 -0
  143. package/dist/daemon/server.js.map +1 -0
  144. package/dist/daemon/service.d.ts +38 -0
  145. package/dist/daemon/service.d.ts.map +1 -0
  146. package/dist/daemon/service.js +275 -0
  147. package/dist/daemon/service.js.map +1 -0
  148. package/dist/daemon/session-cursor.d.ts +3 -0
  149. package/dist/daemon/session-cursor.d.ts.map +1 -0
  150. package/dist/daemon/session-cursor.js +4 -0
  151. package/dist/daemon/session-cursor.js.map +1 -0
  152. package/dist/daemon/session-execution.d.ts +88 -0
  153. package/dist/daemon/session-execution.d.ts.map +1 -0
  154. package/dist/daemon/session-execution.js +2 -0
  155. package/dist/daemon/session-execution.js.map +1 -0
  156. package/dist/daemon/session-executions.d.ts +5 -0
  157. package/dist/daemon/session-executions.d.ts.map +1 -0
  158. package/dist/daemon/session-executions.js +146 -0
  159. package/dist/daemon/session-executions.js.map +1 -0
  160. package/dist/daemon/session-files.d.ts +28 -0
  161. package/dist/daemon/session-files.d.ts.map +1 -0
  162. package/dist/daemon/session-files.js +189 -0
  163. package/dist/daemon/session-files.js.map +1 -0
  164. package/dist/daemon/session-lifecycle-contracts.d.ts +104 -0
  165. package/dist/daemon/session-lifecycle-contracts.d.ts.map +1 -0
  166. package/dist/daemon/session-lifecycle-contracts.js +2 -0
  167. package/dist/daemon/session-lifecycle-contracts.js.map +1 -0
  168. package/dist/daemon/session-lifecycle.d.ts +26 -0
  169. package/dist/daemon/session-lifecycle.d.ts.map +1 -0
  170. package/dist/daemon/session-lifecycle.js +246 -0
  171. package/dist/daemon/session-lifecycle.js.map +1 -0
  172. package/dist/daemon/session-runtime.d.ts +64 -0
  173. package/dist/daemon/session-runtime.d.ts.map +1 -0
  174. package/dist/daemon/session-runtime.js +3 -0
  175. package/dist/daemon/session-runtime.js.map +1 -0
  176. package/dist/daemon/session-services.d.ts +6 -0
  177. package/dist/daemon/session-services.d.ts.map +1 -0
  178. package/dist/daemon/session-services.js +144 -0
  179. package/dist/daemon/session-services.js.map +1 -0
  180. package/dist/daemon/shutdown-error.d.ts +12 -0
  181. package/dist/daemon/shutdown-error.d.ts.map +1 -0
  182. package/dist/daemon/shutdown-error.js +51 -0
  183. package/dist/daemon/shutdown-error.js.map +1 -0
  184. package/dist/daemon/supervisor.d.ts +28 -0
  185. package/dist/daemon/supervisor.d.ts.map +1 -0
  186. package/dist/daemon/supervisor.js +159 -0
  187. package/dist/daemon/supervisor.js.map +1 -0
  188. package/dist/daemon/target.d.ts +55 -0
  189. package/dist/daemon/target.d.ts.map +1 -0
  190. package/dist/daemon/target.js +191 -0
  191. package/dist/daemon/target.js.map +1 -0
  192. package/dist/daemon/tree.d.ts +7 -0
  193. package/dist/daemon/tree.d.ts.map +1 -0
  194. package/dist/daemon/tree.js +126 -0
  195. package/dist/daemon/tree.js.map +1 -0
  196. package/dist/daemon/ui-vocabulary.d.ts +29 -0
  197. package/dist/daemon/ui-vocabulary.d.ts.map +1 -0
  198. package/dist/daemon/ui-vocabulary.js +323 -0
  199. package/dist/daemon/ui-vocabulary.js.map +1 -0
  200. package/dist/daemon/worker.d.ts +5 -0
  201. package/dist/daemon/worker.d.ts.map +1 -0
  202. package/dist/daemon/worker.js +49 -0
  203. package/dist/daemon/worker.js.map +1 -0
  204. package/dist/index.d.ts +4 -0
  205. package/dist/index.d.ts.map +1 -0
  206. package/dist/index.js +12 -0
  207. package/dist/index.js.map +1 -0
  208. package/dist/lock.d.ts +27 -0
  209. package/dist/lock.d.ts.map +1 -0
  210. package/dist/lock.js +432 -0
  211. package/dist/lock.js.map +1 -0
  212. package/dist/logger.d.ts +9 -0
  213. package/dist/logger.d.ts.map +1 -0
  214. package/dist/logger.js +56 -0
  215. package/dist/logger.js.map +1 -0
  216. package/dist/remote/backoff.d.ts +17 -0
  217. package/dist/remote/backoff.d.ts.map +1 -0
  218. package/dist/remote/backoff.js +18 -0
  219. package/dist/remote/backoff.js.map +1 -0
  220. package/dist/remote/batch.d.ts +3 -0
  221. package/dist/remote/batch.d.ts.map +1 -0
  222. package/dist/remote/batch.js +27 -0
  223. package/dist/remote/batch.js.map +1 -0
  224. package/dist/remote/command-journal.d.ts +30 -0
  225. package/dist/remote/command-journal.d.ts.map +1 -0
  226. package/dist/remote/command-journal.js +72 -0
  227. package/dist/remote/command-journal.js.map +1 -0
  228. package/dist/remote/commands.d.ts +48 -0
  229. package/dist/remote/commands.d.ts.map +1 -0
  230. package/dist/remote/commands.js +145 -0
  231. package/dist/remote/commands.js.map +1 -0
  232. package/dist/remote/connector.d.ts +135 -0
  233. package/dist/remote/connector.d.ts.map +1 -0
  234. package/dist/remote/connector.js +1069 -0
  235. package/dist/remote/connector.js.map +1 -0
  236. package/dist/remote/content.d.ts +17 -0
  237. package/dist/remote/content.d.ts.map +1 -0
  238. package/dist/remote/content.js +116 -0
  239. package/dist/remote/content.js.map +1 -0
  240. package/dist/remote/outbox.d.ts +52 -0
  241. package/dist/remote/outbox.d.ts.map +1 -0
  242. package/dist/remote/outbox.js +321 -0
  243. package/dist/remote/outbox.js.map +1 -0
  244. package/dist/remote/platform.d.ts +53 -0
  245. package/dist/remote/platform.d.ts.map +1 -0
  246. package/dist/remote/platform.js +231 -0
  247. package/dist/remote/platform.js.map +1 -0
  248. package/dist/remote/realtime.d.ts +45 -0
  249. package/dist/remote/realtime.d.ts.map +1 -0
  250. package/dist/remote/realtime.js +265 -0
  251. package/dist/remote/realtime.js.map +1 -0
  252. package/dist/remote/sharing.d.ts +16 -0
  253. package/dist/remote/sharing.d.ts.map +1 -0
  254. package/dist/remote/sharing.js +24 -0
  255. package/dist/remote/sharing.js.map +1 -0
  256. package/dist/remote/state.d.ts +52 -0
  257. package/dist/remote/state.d.ts.map +1 -0
  258. package/dist/remote/state.js +156 -0
  259. package/dist/remote/state.js.map +1 -0
  260. package/dist/remote/text.d.ts +11 -0
  261. package/dist/remote/text.d.ts.map +1 -0
  262. package/dist/remote/text.js +188 -0
  263. package/dist/remote/text.js.map +1 -0
  264. package/dist/remote/token.d.ts +39 -0
  265. package/dist/remote/token.d.ts.map +1 -0
  266. package/dist/remote/token.js +238 -0
  267. package/dist/remote/token.js.map +1 -0
  268. package/dist/runtime-factory.d.ts +12 -0
  269. package/dist/runtime-factory.d.ts.map +1 -0
  270. package/dist/runtime-factory.js +12 -0
  271. package/dist/runtime-factory.js.map +1 -0
  272. package/dist/session-history.d.ts +29 -0
  273. package/dist/session-history.d.ts.map +1 -0
  274. package/dist/session-history.js +374 -0
  275. package/dist/session-history.js.map +1 -0
  276. package/dist/setup/dependencies.d.ts +15 -0
  277. package/dist/setup/dependencies.d.ts.map +1 -0
  278. package/dist/setup/dependencies.js +2 -0
  279. package/dist/setup/dependencies.js.map +1 -0
  280. package/dist/setup/open.d.ts +8 -0
  281. package/dist/setup/open.d.ts.map +1 -0
  282. package/dist/setup/open.js +16 -0
  283. package/dist/setup/open.js.map +1 -0
  284. package/dist/version.d.ts +2 -0
  285. package/dist/version.d.ts.map +1 -0
  286. package/dist/version.js +4 -0
  287. package/dist/version.js.map +1 -0
  288. package/package.json +65 -3
@@ -0,0 +1,167 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { isUtf8 } from 'node:buffer';
3
+ import { constants } from 'node:fs';
4
+ import { lstat, open } from 'node:fs/promises';
5
+ import { isAbsolute, join } from 'node:path';
6
+ import { Type } from 'typebox';
7
+ import { JsonValueSchema, assertJson, parseSchema, text } from '@felan-ai/session-protocol';
8
+ import { DaemonSecurityError } from './native-ownership.js';
9
+ const ServiceSchema = Type.Object({
10
+ id: Type.String({ minLength: 1, maxLength: 128, pattern: '^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*$' }),
11
+ major: Type.Integer({ minimum: 1, maximum: 65_535 }),
12
+ use: text(512, 1),
13
+ options: Type.Optional(JsonValueSchema),
14
+ }, { additionalProperties: false });
15
+ const ExtensionSchema = Type.Object({
16
+ package: text(256, 1), grants: Type.Optional(Type.Array(Type.String({ minLength: 1, maxLength: 128 }), { uniqueItems: true })),
17
+ }, { additionalProperties: false });
18
+ const PolicySchema = Type.Object({
19
+ projectTrust: Type.Optional(Type.Union([Type.Literal('allow'), Type.Literal('ask'), Type.Literal('deny')])),
20
+ dependencyInstalls: Type.Optional(Type.Union([Type.Literal('allow'), Type.Literal('ask'), Type.Literal('deny')])),
21
+ }, { additionalProperties: false });
22
+ export const HostConfigSchema = Type.Object({
23
+ version: Type.Literal(1),
24
+ services: Type.Array(ServiceSchema),
25
+ extensions: Type.Array(ExtensionSchema),
26
+ policy: Type.Optional(PolicySchema),
27
+ }, { additionalProperties: false });
28
+ export async function resolveHostComposition(config, manager, resolveSpecifier = (specifier, resolveFrom) => import.meta.resolve(specifier, resolveFrom)) {
29
+ if (!validPackageSpecifier(manager.packageName) || manager.version.length < 1 || manager.version.length > 128) {
30
+ throw new DaemonSecurityError('invalid_manager', 'Managing package identity is invalid.');
31
+ }
32
+ let anchor;
33
+ try {
34
+ anchor = new URL(manager.resolveFrom);
35
+ }
36
+ catch {
37
+ throw new DaemonSecurityError('invalid_manager', 'Managing package resolution anchor is invalid.');
38
+ }
39
+ if (anchor.protocol !== 'file:')
40
+ throw new DaemonSecurityError('invalid_manager', 'Managing package resolution anchor must be a file URL.');
41
+ const resolved = new Map();
42
+ for (const service of config.config.services) {
43
+ if (!resolved.has(service.use)) {
44
+ let url;
45
+ try {
46
+ url = manager.resolveProvider ? manager.resolveProvider(service.use) : resolveSpecifier(service.use, anchor.href);
47
+ }
48
+ catch (error) {
49
+ const reason = error instanceof Error ? `${error.name}: ${error.message}`.replace(/[\u0000-\u001f\u007f]/gu, '?').slice(0, 512) : 'resolution failed';
50
+ throw new DaemonSecurityError('provider_unavailable', `Configured provider ${service.use} is not exported by the managing installation (${reason}).`);
51
+ }
52
+ if (!url.startsWith('file:'))
53
+ throw new DaemonSecurityError('provider_unavailable', `Configured provider ${service.use} did not resolve to an installed file.`);
54
+ resolved.set(service.use, url);
55
+ }
56
+ }
57
+ const providers = config.config.services.map(service => Object.freeze({
58
+ id: service.id, major: service.major, specifier: service.use, moduleUrl: resolved.get(service.use),
59
+ ...(service.options === undefined ? {} : { options: service.options }),
60
+ }));
61
+ const resolvedProviders = [...resolved.entries()].sort(([a], [b]) => a.localeCompare(b));
62
+ const providerDigest = createHash('sha256').update(JSON.stringify({ manager: [manager.packageName, manager.version], services: config.config.services, providers: resolvedProviders })).digest('hex');
63
+ const configDigest = createHash('sha256').update(JSON.stringify({ manager: [manager.packageName, manager.version], config: config.config, providers: resolvedProviders })).digest('hex');
64
+ return Object.freeze({ managerPackage: manager.packageName, managerVersion: manager.version, providerDigest, configDigest, providers: Object.freeze(providers) });
65
+ }
66
+ export async function loadHostConfig(options) {
67
+ let source;
68
+ if (options.explicitPath !== undefined) {
69
+ if (!isAbsolute(options.explicitPath))
70
+ throw new DaemonSecurityError('unsafe_host_config', 'Explicit host configuration must use an absolute path.');
71
+ source = { kind: 'explicit', path: options.explicitPath };
72
+ }
73
+ else {
74
+ const agentPath = join(options.agentDir, 'host.json');
75
+ try {
76
+ await lstat(agentPath);
77
+ source = { kind: 'agent-directory', path: agentPath };
78
+ }
79
+ catch (error) {
80
+ if (error.code !== 'ENOENT')
81
+ throw error;
82
+ if (!options.packagedDefaultPath || !isAbsolute(options.packagedDefaultPath)) {
83
+ throw new DaemonSecurityError('host_config_missing', 'No host.json exists and the managing package supplied no default configuration.');
84
+ }
85
+ source = { kind: 'packaged-default', path: options.packagedDefaultPath };
86
+ }
87
+ }
88
+ const bytes = await readTrustedConfigFile(source);
89
+ let raw;
90
+ try {
91
+ raw = JSON.parse(bytes.toString('utf8'));
92
+ }
93
+ catch {
94
+ throw new DaemonSecurityError('invalid_host_config', 'host.json is not valid JSON.');
95
+ }
96
+ let config;
97
+ try {
98
+ config = parseSchema(HostConfigSchema, raw);
99
+ }
100
+ catch (error) {
101
+ throw new DaemonSecurityError('invalid_host_config', error instanceof Error ? error.message : 'host.json does not match the supported schema.');
102
+ }
103
+ const providers = new Set();
104
+ for (const service of config.services) {
105
+ if (!validPackageSpecifier(service.use))
106
+ throw new DaemonSecurityError('invalid_host_config', `Service ${service.id}@${service.major} must name an installed package export.`);
107
+ const key = `${service.id}@${service.major}`;
108
+ if (providers.has(key))
109
+ throw new DaemonSecurityError('invalid_host_config', `Service ${key} has more than one configured provider.`);
110
+ providers.add(key);
111
+ }
112
+ const extensions = new Set();
113
+ for (const extension of config.extensions) {
114
+ if (!validPackageSpecifier(extension.package))
115
+ throw new DaemonSecurityError('invalid_host_config', 'Extensions must name installed package exports.');
116
+ if (extensions.has(extension.package))
117
+ throw new DaemonSecurityError('invalid_host_config', `Extension ${extension.package} is duplicated.`);
118
+ extensions.add(extension.package);
119
+ if (extension.grants?.some(grant => !/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*@[1-9][0-9]{0,4}$/u.test(grant))) {
120
+ throw new DaemonSecurityError('invalid_host_config', `Extension ${extension.package} has an invalid service grant.`);
121
+ }
122
+ }
123
+ assertJson(config);
124
+ rejectCredentialValues(config);
125
+ const normalized = Buffer.from(JSON.stringify(config));
126
+ return Object.freeze({ config, source, digest: createHash('sha256').update(normalized).digest('hex') });
127
+ }
128
+ const CREDENTIAL_KEY = /^(?:password|passphrase|secret|client.?secret|(?:access|refresh|auth|bearer|api).?token|token|api.?key|private.?key|credentials?)$/iu;
129
+ function rejectCredentialValues(value) {
130
+ if (value === null || typeof value !== 'object')
131
+ return;
132
+ for (const [key, child] of Object.entries(value)) {
133
+ if (CREDENTIAL_KEY.test(key)) {
134
+ throw new DaemonSecurityError('invalid_host_config', 'host.json cannot contain credential values; configure a host-owned secret service.');
135
+ }
136
+ rejectCredentialValues(child);
137
+ }
138
+ }
139
+ export function validPackageSpecifier(specifier) {
140
+ if (specifier.length > 512 || specifier.startsWith('.') || specifier.startsWith('/') || specifier.includes('\\') || specifier.includes(':'))
141
+ return false;
142
+ const segments = specifier.split('/');
143
+ if (segments.some(segment => segment === '.' || segment === '..' || segment.length === 0))
144
+ return false;
145
+ if (specifier.startsWith('@'))
146
+ return segments.length >= 2 && /^@[A-Za-z0-9._-]+$/u.test(segments[0]) && /^[A-Za-z0-9._-]+$/u.test(segments[1]) && segments.slice(2).every(isExportSegment);
147
+ return /^[A-Za-z0-9._-]+$/u.test(segments[0]) && segments.slice(1).every(isExportSegment);
148
+ }
149
+ function isExportSegment(value) { return /^[A-Za-z0-9._~-]+$/u.test(value); }
150
+ /** host.json selects executable providers, so only its owner may be able to change it. */
151
+ async function readTrustedConfigFile(source) {
152
+ let bytes;
153
+ const handle = await open(source.path, constants.O_RDONLY).catch(() => { throw new DaemonSecurityError('unsafe_host_config', 'host.json path is unavailable.'); });
154
+ try {
155
+ const stat = await handle.stat();
156
+ if (!stat.isFile() || (stat.mode & 0o022) !== 0)
157
+ throw new DaemonSecurityError('unsafe_host_config', 'host.json must be a regular file that is not group or world writable.');
158
+ bytes = await handle.readFile();
159
+ }
160
+ finally {
161
+ await handle.close();
162
+ }
163
+ if (!isUtf8(bytes))
164
+ throw new DaemonSecurityError('invalid_host_config', 'host.json must be valid UTF-8.');
165
+ return bytes;
166
+ }
167
+ //# sourceMappingURL=host-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-config.js","sourceRoot":"","sources":["../../src/daemon/host-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ import type { AgentRuntime, ExtensionConfigDefinition, ExtensionConfigOverride, ModelRuntime, RuntimeDependencyInstallResult } from '@felan-ai/agent-core';
2
+ import type { JsonValue, OperationParams, OperationResult, SetupCatalog, SetupJob, SetupStart } from '@felan-ai/session-protocol';
3
+ import type { InteractionBroker } from './broker.js';
4
+ export interface HostConfiguration {
5
+ get(scope: OperationParams<'config.get'>['scope'], model?: {
6
+ provider: string;
7
+ id: string;
8
+ }): Promise<OperationResult<'config.get'>>;
9
+ set(scope: OperationParams<'config.set'>['scope'], input: unknown): Promise<void>;
10
+ prepare(scope: OperationParams<'config.set'>['scope'], input: unknown): void;
11
+ sessionOverrides(input: unknown, previous?: readonly ExtensionConfigOverride[]): {
12
+ extensionId: string;
13
+ source: string;
14
+ values: Record<string, JsonValue>;
15
+ }[];
16
+ sessionValues(overrides: readonly ExtensionConfigOverride[]): Promise<OperationResult<'config.get'>>;
17
+ }
18
+ export interface HostSetup {
19
+ dependency(id: string): {
20
+ readonly label: string;
21
+ readonly description: string;
22
+ } | undefined;
23
+ installApprovedDependency(id: string, signal?: AbortSignal): Promise<RuntimeDependencyInstallResult>;
24
+ catalog(): Promise<SetupCatalog>;
25
+ validateStart(value: SetupStart): void;
26
+ start(request: SetupStart, client: string): SetupJob;
27
+ read(id: string, client: string): SetupJob;
28
+ answer(id: string, promptId: string, text: string, client: string): Promise<void>;
29
+ cancel(id: string, client: string): void;
30
+ prepareOpenLink(id: string, index: number, client: string): () => Promise<void>;
31
+ disconnected(client: string): void;
32
+ beginDrain(): void;
33
+ /** Accepts new jobs again after an abandoned drain. */
34
+ endDrain?(): void;
35
+ drain(): Promise<void>;
36
+ }
37
+ export interface HostServices {
38
+ readonly configuration: HostConfiguration;
39
+ readonly setup: HostSetup;
40
+ prepareRoot?(request: {
41
+ cwd: string;
42
+ extensions?: readonly string[];
43
+ }, caller: {
44
+ recipient?: string;
45
+ signal: AbortSignal;
46
+ }): Promise<{
47
+ cwd: string;
48
+ extensionPaths: readonly string[];
49
+ }>;
50
+ }
51
+ export interface HostServicesRequest {
52
+ readonly agentDir: string;
53
+ readonly homeDir: string;
54
+ readonly runtime: AgentRuntime;
55
+ readonly models: ModelRuntime;
56
+ readonly definitions: readonly ExtensionConfigDefinition[];
57
+ readonly interactions: Pick<InteractionBroker, 'request'>;
58
+ refreshModelAvailability(signal: AbortSignal): Promise<void>;
59
+ assertCurrent(): void;
60
+ }
61
+ //# sourceMappingURL=host-services.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-services.d.ts","sourceRoot":"","sources":["../../src/daemon/host-services.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=host-services.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-services.js","sourceRoot":"","sources":["../../src/daemon/host-services.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ import { type Socket } from 'node:net';
2
+ import { type ControlResponse, type DaemonIdentity } from '@felan-ai/session-protocol';
3
+ import { type ResolvedDaemonTarget } from './target.js';
4
+ import type { DaemonOwnership } from './ownership.js';
5
+ export interface LocalIpcListener {
6
+ close(): void;
7
+ }
8
+ export declare function listenLocalIpc(owner: DaemonOwnership, onConnection: (socket: Socket) => void): Promise<LocalIpcListener>;
9
+ export declare function connectLocalIpc(target: ResolvedDaemonTarget): Promise<Socket>;
10
+ export declare function readinessResponse(owner: DaemonOwnership, version: string, re: string): ControlResponse;
11
+ export declare function serveReadiness(owner: DaemonOwnership, version: string, socket: Socket): void;
12
+ export declare function readControlFrame(socket: Socket, timeoutMs: number): Promise<ControlResponse>;
13
+ export declare function probeDaemon(target: ResolvedDaemonTarget, expected: DaemonIdentity, timeoutMs?: number): Promise<ControlResponse>;
14
+ //# sourceMappingURL=ipc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ipc.d.ts","sourceRoot":"","sources":["../../src/daemon/ipc.ts"],"names":[],"mappings":"AACA,OAAO,EAA6B,KAAK,MAAM,EAAE,MAAM,UAAU,CAAC;AAElE,OAAO,EAA8G,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEnM,OAAO,EAAwE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC9H,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAUtD,MAAM,WAAW,gBAAgB;IAAG,KAAK,IAAI,IAAI,CAAA;CAAE;AACnD,wBAAsB,cAAc,CAAC,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAmE9H;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAKnF;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,eAAe,CAGtG;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAgB5F;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAoBlG;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,oBAAoB,EAAE,QAAQ,EAAE,cAAc,EAAE,SAAS,SAAQ,GAAG,OAAO,CAAC,eAAe,CAAC,CAUrI"}
@@ -0,0 +1,233 @@
1
+ import { closeSync, lstatSync, unlinkSync } from 'node:fs';
2
+ import { createServer } from 'node:net';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { CONTROL_VERSION, PROTOCOL_VERSION, JsonLineDecoder, encodeFrame, parseControlRequest, parseControlResponse } from '@felan-ai/session-protocol';
5
+ import { connectUnix, DaemonSecurityError, listenUnix, peerUid, protectSocket } from './native-ownership.js';
6
+ import { assertPathIdentity, assertTargetIdentity, pathIdentity, pinPathChain } from './target.js';
7
+ function endpointExists(path) { try {
8
+ lstatSync(path);
9
+ return true;
10
+ }
11
+ catch (error) {
12
+ if (error.code === 'ENOENT')
13
+ return false;
14
+ throw error;
15
+ } }
16
+ function validateSocket(target) {
17
+ const stat = lstatSync(target.endpoint, { bigint: true });
18
+ if (!stat.isSocket() || stat.uid !== BigInt(target.uid) || (stat.mode & 63n) !== 0n)
19
+ throw new DaemonSecurityError('unsafe_endpoint', 'Endpoint must be an owner-only Unix socket, never a symlink or other file.');
20
+ for (const pin of pinPathChain(target.runtimeDirectory, target.uid))
21
+ assertPathIdentity(pin);
22
+ return pathIdentity(target.endpoint);
23
+ }
24
+ export async function listenLocalIpc(owner, onConnection) {
25
+ owner.assertCurrent();
26
+ const target = owner.target;
27
+ if (endpointExists(target.endpoint)) {
28
+ const stale = validateSocket(target);
29
+ try {
30
+ const live = await connectUnix(target.endpoint, target.uid, 200);
31
+ live.destroy();
32
+ throw new DaemonSecurityError('endpoint_live', 'A live endpoint exists; never unlink it to force startup.');
33
+ }
34
+ catch (error) {
35
+ if (!(error instanceof DaemonSecurityError) || error.code !== 'stale_endpoint')
36
+ throw error;
37
+ }
38
+ owner.assertCurrent();
39
+ assertPathIdentity(stale);
40
+ unlinkSync(target.endpoint);
41
+ }
42
+ owner.assertCurrent();
43
+ const fd = listenUnix(target.endpoint);
44
+ let closed = false;
45
+ const connections = new Set();
46
+ let pin;
47
+ let server;
48
+ let transferred = false;
49
+ let unwatch = () => { };
50
+ let unsubscribe = () => { };
51
+ function close() {
52
+ unsubscribe();
53
+ if (closed) {
54
+ unwatch();
55
+ return;
56
+ }
57
+ closed = true;
58
+ // Once listen({ fd }) adopts the descriptor, only libuv may close it.
59
+ if (transferred)
60
+ server.close();
61
+ else
62
+ closeSync(fd);
63
+ for (const socket of connections)
64
+ socket.destroy();
65
+ connections.clear();
66
+ try {
67
+ owner.assertCurrent();
68
+ if (pin) {
69
+ assertPathIdentity(pin);
70
+ unwatch();
71
+ unlinkSync(target.endpoint);
72
+ }
73
+ }
74
+ catch { /* Never remove a replacement endpoint or clean up after ownership loss. */ }
75
+ finally {
76
+ unwatch();
77
+ }
78
+ }
79
+ function acceptConnection(socket) {
80
+ socket.on('error', () => { });
81
+ socket.once('close', () => connections.delete(socket));
82
+ if (closed) {
83
+ socket.destroy();
84
+ return;
85
+ }
86
+ try {
87
+ owner.assertCurrent();
88
+ // libuv's uv__accept sets O_NONBLOCK and FD_CLOEXEC before Node emits a connection.
89
+ const peerFd = socket._handle?.fd;
90
+ if (typeof peerFd !== 'number' || !Number.isInteger(peerFd) || peerFd < 0) {
91
+ socket.destroy();
92
+ return;
93
+ }
94
+ try {
95
+ if (peerUid(peerFd) !== target.uid) {
96
+ socket.destroy();
97
+ return;
98
+ }
99
+ }
100
+ catch {
101
+ socket.destroy();
102
+ return;
103
+ }
104
+ owner.assertCurrent();
105
+ if (connections.size >= 64) {
106
+ socket.destroy();
107
+ return;
108
+ }
109
+ connections.add(socket);
110
+ onConnection(socket);
111
+ }
112
+ catch {
113
+ socket.destroy();
114
+ close();
115
+ }
116
+ }
117
+ try {
118
+ protectSocket(target.endpoint);
119
+ pin = validateSocket(target);
120
+ unwatch = owner.watchPath(target.endpoint);
121
+ unsubscribe = owner.onLost(close);
122
+ owner.assertCurrent();
123
+ assertPathIdentity(pin);
124
+ await new Promise((resolve, reject) => {
125
+ server = createServer(acceptConnection);
126
+ server.on('error', error => { reject(error); close(); });
127
+ server.listen({ fd, exclusive: true, backlog: 64 }, resolve);
128
+ transferred = true;
129
+ });
130
+ owner.assertCurrent();
131
+ assertPathIdentity(pin);
132
+ return { close };
133
+ }
134
+ catch (error) {
135
+ close();
136
+ throw error;
137
+ }
138
+ }
139
+ export async function connectLocalIpc(target) {
140
+ const pins = [...pinPathChain(target.runtimeDirectory, target.uid), validateSocket(target)];
141
+ const socket = await connectUnix(target.endpoint, target.uid);
142
+ try {
143
+ for (const pin of pins)
144
+ assertPathIdentity(pin);
145
+ return socket;
146
+ }
147
+ catch (error) {
148
+ socket.destroy();
149
+ throw error;
150
+ }
151
+ }
152
+ export function readinessResponse(owner, version, re) {
153
+ owner.assertCurrent();
154
+ return { control: CONTROL_VERSION, re, identity: owner.identity, daemonVersion: version, supportedProtocol: PROTOCOL_VERSION, state: 'ready', outcome: 'accepted' };
155
+ }
156
+ export function serveReadiness(owner, version, socket) {
157
+ const decoder = new JsonLineDecoder();
158
+ let bytes = 0;
159
+ const timeout = setTimeout(() => socket.destroy(), 2_000);
160
+ socket.once('close', () => clearTimeout(timeout));
161
+ socket.on('data', (chunk) => {
162
+ try {
163
+ owner.assertCurrent();
164
+ bytes += chunk.length;
165
+ if (bytes > 16_384)
166
+ throw new Error('oversize');
167
+ for (const frame of decoder.push(chunk)) {
168
+ const request = parseControlRequest(frame);
169
+ if (request.op !== 'host.status')
170
+ throw new Error('readiness is read-only');
171
+ assertTargetIdentity(owner.target, request.params.expected, owner.identity);
172
+ socket.end(encodeFrame(readinessResponse(owner, version, request.id)));
173
+ }
174
+ }
175
+ catch {
176
+ socket.destroy();
177
+ }
178
+ });
179
+ }
180
+ export async function readControlFrame(socket, timeoutMs) {
181
+ return new Promise((resolve, reject) => {
182
+ const decoder = new JsonLineDecoder();
183
+ let bytes = 0;
184
+ const timeout = setTimeout(() => finish(new DaemonSecurityError('readiness_timeout', 'Daemon did not become ready before the deadline.')), timeoutMs);
185
+ function finish(error, response) {
186
+ clearTimeout(timeout);
187
+ socket.off('data', onData);
188
+ socket.off('error', onError);
189
+ socket.off('end', onEnd);
190
+ if (error)
191
+ reject(error);
192
+ else
193
+ resolve(response);
194
+ }
195
+ function onError() { finish(new DaemonSecurityError('unavailable', 'Daemon readiness connection failed.')); }
196
+ function onEnd() { finish(new DaemonSecurityError('unavailable', 'Daemon closed before readiness.')); }
197
+ function onData(chunk) {
198
+ try {
199
+ bytes += chunk.length;
200
+ if (bytes > 16_384)
201
+ throw new Error('oversize');
202
+ const frames = decoder.push(chunk);
203
+ if (frames.length > 1)
204
+ throw new Error('multiple readiness frames');
205
+ if (frames.length === 1)
206
+ finish(undefined, parseControlResponse(frames[0]));
207
+ }
208
+ catch {
209
+ finish(new DaemonSecurityError('invalid_readiness', 'Malformed or oversized daemon readiness response.'));
210
+ }
211
+ }
212
+ socket.on('data', onData);
213
+ socket.once('error', onError);
214
+ socket.once('end', onEnd);
215
+ });
216
+ }
217
+ export async function probeDaemon(target, expected, timeoutMs = 2_000) {
218
+ const socket = await connectLocalIpc(target);
219
+ try {
220
+ const id = randomUUID();
221
+ const response = readControlFrame(socket, timeoutMs);
222
+ socket.write(encodeFrame({ control: CONTROL_VERSION, id, op: 'host.status', params: { expected } }));
223
+ const ready = await response;
224
+ assertTargetIdentity(target, expected, ready.identity);
225
+ if (ready.re !== id || ready.outcome !== 'accepted' || ready.state !== 'ready' || ready.supportedProtocol !== PROTOCOL_VERSION)
226
+ throw new DaemonSecurityError('invalid_readiness', 'Daemon is not ready for this protocol.');
227
+ return ready;
228
+ }
229
+ finally {
230
+ socket.destroy();
231
+ }
232
+ }
233
+ //# sourceMappingURL=ipc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ipc.js","sourceRoot":"","sources":["../../src/daemon/ipc.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import type { ControlSession } from './control-state.js';
2
+ import type { DaemonOwnership } from './ownership.js';
3
+ /** An unregistered pre-daemon transcript; `LegacySessionIndex.summary` supplies its title and preview. */
4
+ export interface LegacySession {
5
+ readonly id: string;
6
+ readonly cwd: string;
7
+ readonly path: string;
8
+ readonly modifiedAt: number;
9
+ }
10
+ /** Display snippets of the latest Pi session name and the first user message. */
11
+ export interface LegacySummary {
12
+ readonly title: string;
13
+ readonly preview: string;
14
+ }
15
+ type Owner = Pick<DaemonOwnership, 'target'>;
16
+ export declare function legacySessionDirectoryName(cwd: string): string;
17
+ /**
18
+ * Finds unregistered Pi transcripts in the pre-daemon layouts of the owned stores: the per-cwd
19
+ * directories under agentDir/sessions and the top level of each store root (custom session
20
+ * directories). Discovery reads only header lines. A summary needs the whole file, like Pi's
21
+ * session list, so it is read on request. Both are cached until the file changes.
22
+ */
23
+ export declare class LegacySessionIndex {
24
+ private readonly owner;
25
+ private readonly headers;
26
+ private readonly summaries;
27
+ private readonly reading;
28
+ private readonly reads;
29
+ constructor(owner: Owner);
30
+ /** Newest first. Malformed and registered files are skipped; a duplicated ID keeps only its newest file. */
31
+ discover(registered: readonly Pick<ControlSession, 'id' | 'piPath'>[], options?: {
32
+ cwd?: string;
33
+ signal?: AbortSignal;
34
+ }): Promise<LegacySession[]>;
35
+ /** Empty when the file is gone, unreadable or no longer holds this session. */
36
+ summary(session: Pick<LegacySession, 'id' | 'path'>): Promise<LegacySummary>;
37
+ /** Reads summaries in the given order, a few at a time, so listings rarely wait for a whole transcript. */
38
+ warm(sessions: readonly LegacySession[], signal: AbortSignal): Promise<void>;
39
+ private header;
40
+ }
41
+ /** Whether a transcript holds a conversation message. Unreadable files count as conversations, so they are kept. */
42
+ export declare function transcriptHasConversation(path: string): Promise<boolean>;
43
+ /** First user message of a transcript file; empty when absent or unreadable. */
44
+ export declare function readTranscriptPreview(path: string): Promise<string>;
45
+ /** First user message among in-memory Pi session entries. */
46
+ export declare function transcriptPreview(entries: Iterable<unknown>): string;
47
+ export {};
48
+ //# sourceMappingURL=legacy-sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"legacy-sessions.d.ts","sourceRoot":"","sources":["../../src/daemon/legacy-sessions.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGtD,0GAA0G;AAC1G,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC/F;AACD,iFAAiF;AACjF,MAAM,WAAW,aAAa;IAAG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AAEnF,KAAK,KAAK,GAAG,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;AAY7C,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;;;GAKG;AACH,qBAAa,kBAAkB;IAOjB,OAAO,CAAC,QAAQ,CAAC,KAAK;IANlC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsE;IAC9F,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA8E;IACxG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsD;IAE9E,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA4B;gBAErB,KAAK,EAAE,KAAK;IAEzC,4GAA4G;IACtG,QAAQ,CAAC,UAAU,EAAE,SAAS,IAAI,CAAC,cAAc,EAAE,IAAI,GAAG,QAAQ,CAAC,EAAE,EAAE,OAAO,GAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAO,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAiC5J,+EAA+E;IACzE,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC;IAmBlF,2GAA2G;IACrG,IAAI,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;YAIpE,MAAM;CAUrB;AAED,oHAAoH;AACpH,wBAAsB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAW9E;AAED,gFAAgF;AAChF,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEzE;AAED,6DAA6D;AAC7D,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,MAAM,CAIpE"}