lingxios 1.0.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 (298) hide show
  1. package/README.md +54 -0
  2. package/db/schema.sql +306 -0
  3. package/dist/src/app/artifacts.d.ts +8 -0
  4. package/dist/src/app/artifacts.js +114 -0
  5. package/dist/src/app/artifacts.js.map +1 -0
  6. package/dist/src/app/doctor.d.ts +22 -0
  7. package/dist/src/app/doctor.js +44 -0
  8. package/dist/src/app/doctor.js.map +1 -0
  9. package/dist/src/app/index.d.ts +123 -0
  10. package/dist/src/app/index.js +291 -0
  11. package/dist/src/app/index.js.map +1 -0
  12. package/dist/src/app/input.d.ts +22 -0
  13. package/dist/src/app/input.js +60 -0
  14. package/dist/src/app/input.js.map +1 -0
  15. package/dist/src/app/recover-wait.d.ts +5 -0
  16. package/dist/src/app/recover-wait.js +59 -0
  17. package/dist/src/app/recover-wait.js.map +1 -0
  18. package/dist/src/app/resources.d.ts +5 -0
  19. package/dist/src/app/resources.js +9 -0
  20. package/dist/src/app/resources.js.map +1 -0
  21. package/dist/src/app/storage.d.ts +2 -0
  22. package/dist/src/app/storage.js +41 -0
  23. package/dist/src/app/storage.js.map +1 -0
  24. package/dist/src/cli/doctor.d.ts +2 -0
  25. package/dist/src/cli/doctor.js +20 -0
  26. package/dist/src/cli/doctor.js.map +1 -0
  27. package/dist/src/cli/eval.d.ts +2 -0
  28. package/dist/src/cli/eval.js +44 -0
  29. package/dist/src/cli/eval.js.map +1 -0
  30. package/dist/src/config.d.ts +22 -0
  31. package/dist/src/config.js +56 -0
  32. package/dist/src/config.js.map +1 -0
  33. package/dist/src/context/attachments.d.ts +10 -0
  34. package/dist/src/context/attachments.js +18 -0
  35. package/dist/src/context/attachments.js.map +1 -0
  36. package/dist/src/context/document-text.d.ts +1 -0
  37. package/dist/src/context/document-text.js +29 -0
  38. package/dist/src/context/document-text.js.map +1 -0
  39. package/dist/src/context/document-worker.d.ts +1 -0
  40. package/dist/src/context/document-worker.js +62 -0
  41. package/dist/src/context/document-worker.js.map +1 -0
  42. package/dist/src/context/evidence.d.ts +19 -0
  43. package/dist/src/context/evidence.js +37 -0
  44. package/dist/src/context/evidence.js.map +1 -0
  45. package/dist/src/context/request.d.ts +21 -0
  46. package/dist/src/context/request.js +32 -0
  47. package/dist/src/context/request.js.map +1 -0
  48. package/dist/src/context/research-evidence.d.ts +4 -0
  49. package/dist/src/context/research-evidence.js +24 -0
  50. package/dist/src/context/research-evidence.js.map +1 -0
  51. package/dist/src/context/resource-checks.d.ts +7 -0
  52. package/dist/src/context/resource-checks.js +15 -0
  53. package/dist/src/context/resource-checks.js.map +1 -0
  54. package/dist/src/context/task-contract.d.ts +11 -0
  55. package/dist/src/context/task-contract.js +23 -0
  56. package/dist/src/context/task-contract.js.map +1 -0
  57. package/dist/src/context/text.d.ts +2 -0
  58. package/dist/src/context/text.js +7 -0
  59. package/dist/src/context/text.js.map +1 -0
  60. package/dist/src/control-plane/http-server.d.ts +22 -0
  61. package/dist/src/control-plane/http-server.js +196 -0
  62. package/dist/src/control-plane/http-server.js.map +1 -0
  63. package/dist/src/control-plane/memory-store.d.ts +71 -0
  64. package/dist/src/control-plane/memory-store.js +389 -0
  65. package/dist/src/control-plane/memory-store.js.map +1 -0
  66. package/dist/src/control-plane/pg-store.d.ts +62 -0
  67. package/dist/src/control-plane/pg-store.js +386 -0
  68. package/dist/src/control-plane/pg-store.js.map +1 -0
  69. package/dist/src/control-plane/service.d.ts +52 -0
  70. package/dist/src/control-plane/service.js +630 -0
  71. package/dist/src/control-plane/service.js.map +1 -0
  72. package/dist/src/control-plane/stores.d.ts +184 -0
  73. package/dist/src/control-plane/stores.js +19 -0
  74. package/dist/src/control-plane/stores.js.map +1 -0
  75. package/dist/src/errors.d.ts +66 -0
  76. package/dist/src/errors.js +102 -0
  77. package/dist/src/errors.js.map +1 -0
  78. package/dist/src/eval/calibration.d.ts +16 -0
  79. package/dist/src/eval/calibration.js +28 -0
  80. package/dist/src/eval/calibration.js.map +1 -0
  81. package/dist/src/eval/index.d.ts +40 -0
  82. package/dist/src/eval/index.js +40 -0
  83. package/dist/src/eval/index.js.map +1 -0
  84. package/dist/src/eval/review.d.ts +20 -0
  85. package/dist/src/eval/review.js +49 -0
  86. package/dist/src/eval/review.js.map +1 -0
  87. package/dist/src/host/http-client.d.ts +48 -0
  88. package/dist/src/host/http-client.js +127 -0
  89. package/dist/src/host/http-client.js.map +1 -0
  90. package/dist/src/host/port.d.ts +26 -0
  91. package/dist/src/host/port.js +2 -0
  92. package/dist/src/host/port.js.map +1 -0
  93. package/dist/src/index.d.ts +17 -0
  94. package/dist/src/index.js +9 -0
  95. package/dist/src/index.js.map +1 -0
  96. package/dist/src/integrations/lingxiloop/actions.d.ts +25 -0
  97. package/dist/src/integrations/lingxiloop/actions.js +77 -0
  98. package/dist/src/integrations/lingxiloop/actions.js.map +1 -0
  99. package/dist/src/integrations/lingxiloop/app.d.ts +167 -0
  100. package/dist/src/integrations/lingxiloop/app.js +434 -0
  101. package/dist/src/integrations/lingxiloop/app.js.map +1 -0
  102. package/dist/src/integrations/lingxiloop/approvals.d.ts +148 -0
  103. package/dist/src/integrations/lingxiloop/approvals.js +540 -0
  104. package/dist/src/integrations/lingxiloop/approvals.js.map +1 -0
  105. package/dist/src/integrations/lingxiloop/attachments.d.ts +8 -0
  106. package/dist/src/integrations/lingxiloop/attachments.js +38 -0
  107. package/dist/src/integrations/lingxiloop/attachments.js.map +1 -0
  108. package/dist/src/integrations/lingxiloop/calendar-approvals.d.ts +21 -0
  109. package/dist/src/integrations/lingxiloop/calendar-approvals.js +126 -0
  110. package/dist/src/integrations/lingxiloop/calendar-approvals.js.map +1 -0
  111. package/dist/src/integrations/lingxiloop/calendar-writes.d.ts +15 -0
  112. package/dist/src/integrations/lingxiloop/calendar-writes.js +79 -0
  113. package/dist/src/integrations/lingxiloop/calendar-writes.js.map +1 -0
  114. package/dist/src/integrations/lingxiloop/calendar.d.ts +19 -0
  115. package/dist/src/integrations/lingxiloop/calendar.js +43 -0
  116. package/dist/src/integrations/lingxiloop/calendar.js.map +1 -0
  117. package/dist/src/integrations/lingxiloop/canvas-events.d.ts +7 -0
  118. package/dist/src/integrations/lingxiloop/canvas-events.js +53 -0
  119. package/dist/src/integrations/lingxiloop/canvas-events.js.map +1 -0
  120. package/dist/src/integrations/lingxiloop/canvas-summary.d.ts +5 -0
  121. package/dist/src/integrations/lingxiloop/canvas-summary.js +52 -0
  122. package/dist/src/integrations/lingxiloop/canvas-summary.js.map +1 -0
  123. package/dist/src/integrations/lingxiloop/canvas-work-report.d.ts +12 -0
  124. package/dist/src/integrations/lingxiloop/canvas-work-report.js +120 -0
  125. package/dist/src/integrations/lingxiloop/canvas-work-report.js.map +1 -0
  126. package/dist/src/integrations/lingxiloop/canvas-work.d.ts +11 -0
  127. package/dist/src/integrations/lingxiloop/canvas-work.js +306 -0
  128. package/dist/src/integrations/lingxiloop/canvas-work.js.map +1 -0
  129. package/dist/src/integrations/lingxiloop/canvas.d.ts +12 -0
  130. package/dist/src/integrations/lingxiloop/canvas.js +79 -0
  131. package/dist/src/integrations/lingxiloop/canvas.js.map +1 -0
  132. package/dist/src/integrations/lingxiloop/chat.d.ts +11 -0
  133. package/dist/src/integrations/lingxiloop/chat.js +46 -0
  134. package/dist/src/integrations/lingxiloop/chat.js.map +1 -0
  135. package/dist/src/integrations/lingxiloop/document-approvals.d.ts +21 -0
  136. package/dist/src/integrations/lingxiloop/document-approvals.js +75 -0
  137. package/dist/src/integrations/lingxiloop/document-approvals.js.map +1 -0
  138. package/dist/src/integrations/lingxiloop/document-content.d.ts +80 -0
  139. package/dist/src/integrations/lingxiloop/document-content.js +195 -0
  140. package/dist/src/integrations/lingxiloop/document-content.js.map +1 -0
  141. package/dist/src/integrations/lingxiloop/document-writes.d.ts +8 -0
  142. package/dist/src/integrations/lingxiloop/document-writes.js +49 -0
  143. package/dist/src/integrations/lingxiloop/document-writes.js.map +1 -0
  144. package/dist/src/integrations/lingxiloop/documents.d.ts +22 -0
  145. package/dist/src/integrations/lingxiloop/documents.js +38 -0
  146. package/dist/src/integrations/lingxiloop/documents.js.map +1 -0
  147. package/dist/src/integrations/lingxiloop/event-outbox.d.ts +5 -0
  148. package/dist/src/integrations/lingxiloop/event-outbox.js +47 -0
  149. package/dist/src/integrations/lingxiloop/event-outbox.js.map +1 -0
  150. package/dist/src/integrations/lingxiloop/index.d.ts +3 -0
  151. package/dist/src/integrations/lingxiloop/index.js +3 -0
  152. package/dist/src/integrations/lingxiloop/index.js.map +1 -0
  153. package/dist/src/integrations/lingxiloop/learning-attempts.d.ts +13 -0
  154. package/dist/src/integrations/lingxiloop/learning-attempts.js +58 -0
  155. package/dist/src/integrations/lingxiloop/learning-attempts.js.map +1 -0
  156. package/dist/src/integrations/lingxiloop/learning-evaluation.d.ts +8 -0
  157. package/dist/src/integrations/lingxiloop/learning-evaluation.js +64 -0
  158. package/dist/src/integrations/lingxiloop/learning-evaluation.js.map +1 -0
  159. package/dist/src/integrations/lingxiloop/learning-evidence.d.ts +7 -0
  160. package/dist/src/integrations/lingxiloop/learning-evidence.js +88 -0
  161. package/dist/src/integrations/lingxiloop/learning-evidence.js.map +1 -0
  162. package/dist/src/integrations/lingxiloop/learning-missions.d.ts +18 -0
  163. package/dist/src/integrations/lingxiloop/learning-missions.js +95 -0
  164. package/dist/src/integrations/lingxiloop/learning-missions.js.map +1 -0
  165. package/dist/src/integrations/lingxiloop/learning.d.ts +22 -0
  166. package/dist/src/integrations/lingxiloop/learning.js +150 -0
  167. package/dist/src/integrations/lingxiloop/learning.js.map +1 -0
  168. package/dist/src/integrations/lingxiloop/memory.d.ts +14 -0
  169. package/dist/src/integrations/lingxiloop/memory.js +133 -0
  170. package/dist/src/integrations/lingxiloop/memory.js.map +1 -0
  171. package/dist/src/integrations/lingxiloop/polls.d.ts +9 -0
  172. package/dist/src/integrations/lingxiloop/polls.js +47 -0
  173. package/dist/src/integrations/lingxiloop/polls.js.map +1 -0
  174. package/dist/src/integrations/lingxiloop/presentations.d.ts +11 -0
  175. package/dist/src/integrations/lingxiloop/presentations.js +34 -0
  176. package/dist/src/integrations/lingxiloop/presentations.js.map +1 -0
  177. package/dist/src/integrations/lingxiloop/questionnaire.d.ts +21 -0
  178. package/dist/src/integrations/lingxiloop/questionnaire.js +57 -0
  179. package/dist/src/integrations/lingxiloop/questionnaire.js.map +1 -0
  180. package/dist/src/integrations/lingxiloop/research.d.ts +19 -0
  181. package/dist/src/integrations/lingxiloop/research.js +20 -0
  182. package/dist/src/integrations/lingxiloop/research.js.map +1 -0
  183. package/dist/src/integrations/lingxiloop/routines.d.ts +91 -0
  184. package/dist/src/integrations/lingxiloop/routines.js +198 -0
  185. package/dist/src/integrations/lingxiloop/routines.js.map +1 -0
  186. package/dist/src/integrations/lingxiloop/service-contracts.d.ts +1045 -0
  187. package/dist/src/integrations/lingxiloop/service-contracts.js +2 -0
  188. package/dist/src/integrations/lingxiloop/service-contracts.js.map +1 -0
  189. package/dist/src/integrations/lingxiloop/teacher-context.d.ts +32 -0
  190. package/dist/src/integrations/lingxiloop/teacher-context.js +25 -0
  191. package/dist/src/integrations/lingxiloop/teacher-context.js.map +1 -0
  192. package/dist/src/integrations/lingxiloop/teacher-digest.d.ts +13 -0
  193. package/dist/src/integrations/lingxiloop/teacher-digest.js +152 -0
  194. package/dist/src/integrations/lingxiloop/teacher-digest.js.map +1 -0
  195. package/dist/src/integrations/lingxiloop/teacher-preview.d.ts +22 -0
  196. package/dist/src/integrations/lingxiloop/teacher-preview.js +41 -0
  197. package/dist/src/integrations/lingxiloop/teacher-preview.js.map +1 -0
  198. package/dist/src/integrations/lingxiloop/teacher.d.ts +24 -0
  199. package/dist/src/integrations/lingxiloop/teacher.js +224 -0
  200. package/dist/src/integrations/lingxiloop/teacher.js.map +1 -0
  201. package/dist/src/kernel/manager.d.ts +52 -0
  202. package/dist/src/kernel/manager.js +407 -0
  203. package/dist/src/kernel/manager.js.map +1 -0
  204. package/dist/src/logging.d.ts +21 -0
  205. package/dist/src/logging.js +54 -0
  206. package/dist/src/logging.js.map +1 -0
  207. package/dist/src/memory/evidence.d.ts +6 -0
  208. package/dist/src/memory/evidence.js +43 -0
  209. package/dist/src/memory/evidence.js.map +1 -0
  210. package/dist/src/memory/processor.d.ts +3 -0
  211. package/dist/src/memory/processor.js +66 -0
  212. package/dist/src/memory/processor.js.map +1 -0
  213. package/dist/src/memory/semantic.d.ts +19 -0
  214. package/dist/src/memory/semantic.js +93 -0
  215. package/dist/src/memory/semantic.js.map +1 -0
  216. package/dist/src/memory/store.d.ts +20 -0
  217. package/dist/src/memory/store.js +34 -0
  218. package/dist/src/memory/store.js.map +1 -0
  219. package/dist/src/memory/synthesis.d.ts +24 -0
  220. package/dist/src/memory/synthesis.js +138 -0
  221. package/dist/src/memory/synthesis.js.map +1 -0
  222. package/dist/src/metrics.d.ts +43 -0
  223. package/dist/src/metrics.js +130 -0
  224. package/dist/src/metrics.js.map +1 -0
  225. package/dist/src/model/driver.d.ts +60 -0
  226. package/dist/src/model/driver.js +2 -0
  227. package/dist/src/model/driver.js.map +1 -0
  228. package/dist/src/model/embeddings.d.ts +24 -0
  229. package/dist/src/model/embeddings.js +97 -0
  230. package/dist/src/model/embeddings.js.map +1 -0
  231. package/dist/src/model/openai.d.ts +45 -0
  232. package/dist/src/model/openai.js +340 -0
  233. package/dist/src/model/openai.js.map +1 -0
  234. package/dist/src/outcome/assessment.d.ts +16 -0
  235. package/dist/src/outcome/assessment.js +45 -0
  236. package/dist/src/outcome/assessment.js.map +1 -0
  237. package/dist/src/outcome/content-check.d.ts +19 -0
  238. package/dist/src/outcome/content-check.js +44 -0
  239. package/dist/src/outcome/content-check.js.map +1 -0
  240. package/dist/src/outcome/envelope.d.ts +34 -0
  241. package/dist/src/outcome/envelope.js +42 -0
  242. package/dist/src/outcome/envelope.js.map +1 -0
  243. package/dist/src/protocol/constants.d.ts +25 -0
  244. package/dist/src/protocol/constants.js +26 -0
  245. package/dist/src/protocol/constants.js.map +1 -0
  246. package/dist/src/protocol/kernel-wire.d.ts +74 -0
  247. package/dist/src/protocol/kernel-wire.js +2 -0
  248. package/dist/src/protocol/kernel-wire.js.map +1 -0
  249. package/dist/src/protocol/outcome.d.ts +16 -0
  250. package/dist/src/protocol/outcome.js +14 -0
  251. package/dist/src/protocol/outcome.js.map +1 -0
  252. package/dist/src/protocol/types.d.ts +266 -0
  253. package/dist/src/protocol/types.js +19 -0
  254. package/dist/src/protocol/types.js.map +1 -0
  255. package/dist/src/research/address.d.ts +2 -0
  256. package/dist/src/research/address.js +32 -0
  257. package/dist/src/research/address.js.map +1 -0
  258. package/dist/src/research/fetch.d.ts +7 -0
  259. package/dist/src/research/fetch.js +83 -0
  260. package/dist/src/research/fetch.js.map +1 -0
  261. package/dist/src/research/index.d.ts +26 -0
  262. package/dist/src/research/index.js +109 -0
  263. package/dist/src/research/index.js.map +1 -0
  264. package/dist/src/runtime/compaction.d.ts +41 -0
  265. package/dist/src/runtime/compaction.js +86 -0
  266. package/dist/src/runtime/compaction.js.map +1 -0
  267. package/dist/src/runtime/corrections.d.ts +20 -0
  268. package/dist/src/runtime/corrections.js +27 -0
  269. package/dist/src/runtime/corrections.js.map +1 -0
  270. package/dist/src/runtime/policy.d.ts +42 -0
  271. package/dist/src/runtime/policy.js +91 -0
  272. package/dist/src/runtime/policy.js.map +1 -0
  273. package/dist/src/runtime/resource-refresh.d.ts +8 -0
  274. package/dist/src/runtime/resource-refresh.js +37 -0
  275. package/dist/src/runtime/resource-refresh.js.map +1 -0
  276. package/dist/src/runtime/runtime.d.ts +51 -0
  277. package/dist/src/runtime/runtime.js +804 -0
  278. package/dist/src/runtime/runtime.js.map +1 -0
  279. package/dist/src/runtime/tool.d.ts +13 -0
  280. package/dist/src/runtime/tool.js +42 -0
  281. package/dist/src/runtime/tool.js.map +1 -0
  282. package/dist/src/ui/index.d.ts +27 -0
  283. package/dist/src/ui/index.js +54 -0
  284. package/dist/src/ui/index.js.map +1 -0
  285. package/dist/src/versions.d.ts +9 -0
  286. package/dist/src/versions.js +11 -0
  287. package/dist/src/versions.js.map +1 -0
  288. package/dist/src/worker/index.d.ts +3 -0
  289. package/dist/src/worker/index.js +57 -0
  290. package/dist/src/worker/index.js.map +1 -0
  291. package/dist/src/worker/main.d.ts +2 -0
  292. package/dist/src/worker/main.js +9 -0
  293. package/dist/src/worker/main.js.map +1 -0
  294. package/dist/src/worker/worker.d.ts +45 -0
  295. package/dist/src/worker/worker.js +154 -0
  296. package/dist/src/worker/worker.js.map +1 -0
  297. package/kernel/runner.py +507 -0
  298. package/package.json +83 -0
@@ -0,0 +1,8 @@
1
+ import { type RequestAttachment } from '../../context/attachments.js';
2
+ import type { LingxiLoopServices, NativeMessage } from './service-contracts.js';
3
+ export declare function readRequestAttachments(services: Pick<LingxiLoopServices, 'storage'>, messages: NativeMessage[], input: {
4
+ companyId: string;
5
+ channelId: string;
6
+ channelType: number;
7
+ clientMsgNos: string[];
8
+ }): Promise<RequestAttachment[]>;
@@ -0,0 +1,38 @@
1
+ import { decodeSourceText } from '../../context/text.js';
2
+ import { extractDocumentText } from '../../context/document-text.js';
3
+ import { createHash } from 'node:crypto';
4
+ import { snapshotAttachments } from '../../context/attachments.js';
5
+ export async function readRequestAttachments(services, messages, input) {
6
+ if (!Array.isArray(input.clientMsgNos) || input.clientMsgNos.length > 20
7
+ || input.clientMsgNos.some(id => typeof id !== 'string' || !id.trim())
8
+ || new Set(input.clientMsgNos).size !== input.clientMsgNos.length)
9
+ throw new Error('invalid attachment message references');
10
+ if (!input.clientMsgNos.length)
11
+ return [];
12
+ if (!services.storage?.readObjectBounded)
13
+ throw new Error('native bounded storage reader is required for request attachments');
14
+ const attachments = [];
15
+ for (const id of input.clientMsgNos) {
16
+ const message = messages.find(item => item.clientMsgNo === id && item.channelId === input.channelId && item.channelType === input.channelType);
17
+ const data = message?.payload.data;
18
+ if (message?.payload.version !== 1 || message.payload.kind !== 'attachment' || !data
19
+ || typeof data['key'] !== 'string' || !data['key'].startsWith(`attachments/${input.companyId}/`)
20
+ || typeof data['name'] !== 'string' || !data['name'].trim() || typeof data['mime'] !== 'string'
21
+ || !Number.isSafeInteger(data['size']) || Number(data['size']) < 0 || Number(data['size']) > 16 * 1024 * 1024)
22
+ throw new Error('invalid or unavailable committed request attachment');
23
+ const received = await services.storage.readObjectBounded(data['key'], 16 * 1024 * 1024);
24
+ if (!(received instanceof Uint8Array) || received.byteLength !== data['size'])
25
+ throw new Error('attachment bytes do not match committed size');
26
+ // Storage may reuse its buffer while asynchronous parsing is in flight.
27
+ const bytes = Uint8Array.from(received);
28
+ const mime = data['mime'].split(';')[0].trim().toLowerCase();
29
+ const text = mime.startsWith('text/') || ['application/json', 'application/xml'].includes(mime)
30
+ ? decodeSourceText(bytes)
31
+ : mime === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ? await extractDocumentText(bytes, 'docx')
32
+ : mime === 'application/pdf' ? await extractDocumentText(bytes, 'pdf') : undefined;
33
+ attachments.push({ id, sourceVersion: `sha256:${createHash('sha256').update(bytes).digest('hex')}`, name: data['name'],
34
+ mimeType: data['mime'], size: bytes.byteLength, ...(text === undefined ? {} : { text }) });
35
+ }
36
+ return snapshotAttachments(attachments);
37
+ }
38
+ //# sourceMappingURL=attachments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../../../src/integrations/lingxiloop/attachments.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { type SqlPool } from '../../control-plane/pg-store.js';
2
+ import type { HostAction, WorkItem } from '../../protocol/types.js';
3
+ import type { LingxiLoopServices } from './service-contracts.js';
4
+ type Services = Pick<LingxiLoopServices, 'calendar' | 'permissionService'>;
5
+ export declare function requestCalendarApproval(database: SqlPool, services: Services, work: Omit<WorkItem, 'leaseToken'>, action: HostAction): Promise<import("../../protocol/types.js").HostActionResult>;
6
+ export declare function approveCalendar(database: SqlPool, services: Services, input: {
7
+ companyId: string;
8
+ userId: string;
9
+ approvalId: string;
10
+ }): Promise<{
11
+ status: "continuation_unavailable";
12
+ workId: string;
13
+ result: unknown;
14
+ } | {
15
+ status: "already_resumed";
16
+ workId: string;
17
+ } | {
18
+ status: "resumed";
19
+ workId: string;
20
+ }>;
21
+ export {};
@@ -0,0 +1,126 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { isDeepStrictEqual } from 'node:util';
3
+ import { withTransaction } from '../../control-plane/pg-store.js';
4
+ import { inspectApproval, persistApproval, resumeApproved } from './approvals.js';
5
+ import { assertCalendarAgent, queueCalendarEvent } from './calendar-writes.js';
6
+ /** Build the same scoped preview at request time and immediately before the approved mutation. */
7
+ async function calendarApproval(database, services, work, action, approverId) {
8
+ const api = services.calendar?.writes;
9
+ if (!api || !work.principalId)
10
+ throw new Error('calendar write bindings and original human principal are required');
11
+ if (action.action !== 'calendar.create' && action.action !== 'calendar.delete')
12
+ throw new Error('unsupported calendar approval');
13
+ await assertCalendarAgent(database, work);
14
+ const permissions = api.createPermissionService(database, { lockDependencies: true });
15
+ for (const userId of new Set([work.principalId, ...(approverId ? [approverId] : [])])) {
16
+ await permissions.assertCan({ actorUserId: userId, companyId: work.tenantId,
17
+ action: 'conversation:read', resource: { type: 'conversation', id: work.sessionId } });
18
+ }
19
+ const room = await database.query('SELECT project_id FROM conversations WHERE id=$1 AND company_id=$2 FOR SHARE', [work.sessionId, work.tenantId]);
20
+ const projectId = room.rows[0]?.['project_id'];
21
+ if (typeof projectId !== 'string' || !projectId)
22
+ throw new Error('calendar project scope is unavailable');
23
+ const scope = { companyId: work.tenantId, projectId, userId: work.principalId };
24
+ let notification;
25
+ const application = new api.CalendarApplication(database, { publish: async (event) => { notification = event; } }, { dispatch: async () => { throw new Error('approval cannot dispatch calendar tasks directly'); } });
26
+ const create = action.action === 'calendar.create';
27
+ const { eventId, expected } = action.args;
28
+ if (!create && (Object.keys(action.args).some(key => !['eventId', 'expected'].includes(key))
29
+ || typeof eventId !== 'string' || !eventId.trim() || eventId.length > 2000
30
+ || !expected || typeof expected !== 'object' || Array.isArray(expected) || JSON.stringify(expected).length > 32_000))
31
+ throw new Error('calendar.delete requires eventId and the complete observed event');
32
+ for (const userId of new Set([work.principalId, ...(approverId ? [approverId] : [])])) {
33
+ await permissions.assertCan({ actorUserId: userId, companyId: work.tenantId, projectId,
34
+ action: 'calendar:write', resource: create ? { type: 'project', id: projectId } : { type: 'calendar_event', id: eventId } });
35
+ }
36
+ const input = create ? api.createCalendarEventRequestSchema.parse(action.args) : undefined;
37
+ if (input?.kind === 'agent_task' && !input.targetConversationId)
38
+ input.targetConversationId = work.sessionId;
39
+ if (input?.targetConversationId) {
40
+ for (const userId of new Set([work.principalId, ...(approverId ? [approverId] : [])])) {
41
+ await permissions.assertCan({ actorUserId: userId, companyId: work.tenantId, projectId,
42
+ action: 'conversation:write', resource: { type: 'conversation', id: input.targetConversationId } });
43
+ }
44
+ }
45
+ if (!create) {
46
+ const target = await database.query('SELECT id FROM calendar_events WHERE id=$1 AND company_id=$2 AND project_id=$3 FOR UPDATE', [eventId, work.tenantId, projectId]);
47
+ if (target.rows.length !== 1 || !isDeepStrictEqual(await application.get(scope, eventId), expected))
48
+ throw new Error('calendar event changed; read it again before deleting');
49
+ }
50
+ // Dates are represented identically in persisted approval JSON and subsequent previews.
51
+ const preview = JSON.parse(JSON.stringify({ projectId, conversationId: work.sessionId,
52
+ ...(create ? { input } : { event: expected }) }));
53
+ return { preview, apply: async () => {
54
+ const id = create ? `ce-${createHash('sha256').update(action.idempotencyKey).digest('hex')}` : eventId;
55
+ const event = input ? await application.create(scope, input, { eventId: id }) : await application.delete(scope, id);
56
+ const persisted = await database.query('SELECT id FROM calendar_events WHERE id=$1 AND company_id=$2 AND project_id=$3', [id, work.tenantId, projectId]);
57
+ if (persisted.rows.length !== (create ? 1 : 0) || (!create && !('ok' in event && event.ok === true)))
58
+ throw new Error('calendar mutation postcondition was not observed');
59
+ if (input) {
60
+ const actual = await application.get(scope, id);
61
+ const fields = JSON.parse(JSON.stringify(input));
62
+ if (actual.id !== id || !isDeepStrictEqual(event, actual)
63
+ || !Object.entries(fields).every(([key, value]) => isDeepStrictEqual(Reflect.get(actual, key), value)))
64
+ throw new Error('created calendar event does not match the approved fields');
65
+ }
66
+ if (!notification || notification.type !== 'calendar.changed' || notification.kind !== (create ? 'event.created' : 'event.deleted')
67
+ || notification.eventId !== id || notification.companyId !== work.tenantId || notification.workspaceId !== projectId)
68
+ throw new Error('calendar mutation notification is invalid');
69
+ await queueCalendarEvent(database, work, action, { ...notification, actorId: work.agentId });
70
+ return { eventId: id, ...(create ? { event } : { deleted: true }), notification: 'queued' };
71
+ } };
72
+ }
73
+ export async function requestCalendarApproval(database, services, work, action) {
74
+ return withTransaction(database, async (client) => {
75
+ await client.query("SET LOCAL lock_timeout='5s'");
76
+ await client.query("SET LOCAL statement_timeout='15s'");
77
+ const { preview } = await calendarApproval(client, services, work, action);
78
+ return persistApproval(client, work, action, { summary: action.action === 'calendar.create' ? 'Create the reviewed calendar event' : 'Delete the reviewed calendar event',
79
+ scope: { projectId: preview['projectId'], conversationId: work.sessionId }, preview });
80
+ });
81
+ }
82
+ export async function approveCalendar(database, services, input) {
83
+ const reviewed = await inspectApproval(database, services, input);
84
+ if (!['calendar.create', 'calendar.delete'].includes(reviewed.action.action))
85
+ throw new Error('unsupported calendar approval');
86
+ if (reviewed.status === 'EXECUTED')
87
+ return resumeApproved(database, input, reviewed);
88
+ if (reviewed.status !== 'PENDING')
89
+ throw new Error('calendar approval is no longer pending');
90
+ await withTransaction(database, async (client) => {
91
+ await client.query("SET LOCAL lock_timeout='5s'");
92
+ await client.query("SET LOCAL statement_timeout='15s'");
93
+ const pending = await client.query(`SELECT intent.intent FROM approvals approval
94
+ JOIN lingxios.agent_work_items work ON work.id=approval.work_id AND work.tenant_id=approval.company_id
95
+ JOIN lingxios.agent_action_intents intent ON intent.idempotency_key=approval.idempotency_key
96
+ JOIN lingxios.agent_os_sessions session ON session.tenant_id=work.tenant_id AND session.agent_id=work.agent_id
97
+ AND session.session_id=work.session_id AND session.thread_id IS NOT DISTINCT FROM work.thread_id
98
+ WHERE approval.id=$1 AND approval.company_id=$2 AND approval.status='PENDING' AND approval.expires_at>NOW()
99
+ AND approval.idempotency_key=$3 AND approval.args=$4::jsonb AND approval.preview=$5::jsonb
100
+ AND approval.action=$7 AND work.status='completed' AND work.cancel_requested_at IS NULL
101
+ AND work.goal_outcome->>'status'='awaiting_approval' AND work.goal_outcome->>'approvalId'=$1
102
+ AND (work.goal_outcome->>'requestVersion')::integer=$6 AND jsonb_array_length(work.steer_inputs)+1=$6
103
+ AND session.request_snapshot->>'workId'=work.id AND session.request_snapshot->'revisions'=work.steer_inputs
104
+ FOR UPDATE OF approval,work,session`, [input.approvalId, input.companyId, reviewed.action.idempotencyKey,
105
+ JSON.stringify(reviewed.action.args), JSON.stringify(reviewed.preview), reviewed.requestVersion, reviewed.action.action]);
106
+ const intent = pending.rows[0]?.['intent'];
107
+ if (!intent)
108
+ throw new Error('calendar approval expired or changed before execution');
109
+ const permissions = services.calendar.writes.createPermissionService(client, { lockDependencies: true });
110
+ await permissions.assertCan({ actorUserId: input.userId, companyId: input.companyId,
111
+ action: 'agent_approval:resolve', resource: { type: 'approval', id: input.approvalId } });
112
+ const work = { id: intent.workId, tenantId: intent.tenantId, agentId: intent.agentId, sessionId: intent.sessionId,
113
+ ...(intent.principalId ? { principalId: intent.principalId } : {}) };
114
+ const prepared = await calendarApproval(client, services, work, reviewed.action, input.userId);
115
+ if (!isDeepStrictEqual(prepared.preview, reviewed.preview))
116
+ throw new Error('calendar approval preview is stale');
117
+ const value = await prepared.apply();
118
+ await client.query(`UPDATE approvals SET status='EXECUTED',resolved_at=NOW(),resolved_by=$2,executed_at=NOW(),result=$3::jsonb,error=NULL WHERE id=$1`, [input.approvalId, input.userId, JSON.stringify(value)]);
119
+ const receipt = await client.query(`UPDATE lingxios.agent_action_ledger SET result=$2::jsonb
120
+ WHERE idempotency_key=$1 AND result->'approval'->>'id'=$3 RETURNING idempotency_key`, [reviewed.action.idempotencyKey, JSON.stringify({ ok: true, value }), input.approvalId]);
121
+ if (receipt.rows.length !== 1)
122
+ throw new Error('calendar approval receipt is missing');
123
+ });
124
+ return resumeApproved(database, input, reviewed);
125
+ }
126
+ //# sourceMappingURL=calendar-approvals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar-approvals.js","sourceRoot":"","sources":["../../../../src/integrations/lingxiloop/calendar-approvals.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { type SqlPool, type SqlQueryable } from '../../control-plane/pg-store.js';
2
+ import type { HostAction, WorkItem } from '../../protocol/types.js';
3
+ import type { LingxiLoopServices, NativeCalendarChanged } from './service-contracts.js';
4
+ export declare function updateCalendar(database: SqlPool, services: Pick<LingxiLoopServices, 'calendar'>, work: Omit<WorkItem, 'leaseToken'>, action: HostAction): Promise<{
5
+ event: {
6
+ id: string;
7
+ title: string;
8
+ startAt: string;
9
+ };
10
+ notification: "queued";
11
+ }>;
12
+ export declare function assertCalendarAgent(database: SqlQueryable, work: Pick<WorkItem, 'tenantId' | 'agentId' | 'sessionId'>): Promise<void>;
13
+ /** Written in the same transaction as the native mutation, including approved writes. */
14
+ export declare function queueCalendarEvent(database: SqlQueryable, work: Pick<WorkItem, 'id'>, action: HostAction, event: NativeCalendarChanged): Promise<void>;
15
+ export declare function flushCalendarEvents(database: SqlQueryable, services: Pick<LingxiLoopServices, 'calendar'>): Promise<void>;
@@ -0,0 +1,79 @@
1
+ import { isDeepStrictEqual } from 'node:util';
2
+ import { flushEventOutbox } from './event-outbox.js';
3
+ import { withTransaction } from '../../control-plane/pg-store.js';
4
+ export async function updateCalendar(database, services, work, action) {
5
+ const api = services.calendar?.writes;
6
+ if (!api || !work.principalId || action.action !== 'calendar.update')
7
+ throw new Error('calendar write bindings and original human principal are required');
8
+ if (Object.keys(action.args).some(key => !['eventId', 'expected', 'patch'].includes(key)))
9
+ throw new Error('unknown calendar update argument');
10
+ const { eventId, expected } = action.args;
11
+ if (typeof eventId !== 'string' || !eventId.trim() || eventId.length > 2000)
12
+ throw new Error('eventId is required');
13
+ if (!expected || typeof expected !== 'object' || Array.isArray(expected) || JSON.stringify(expected).length > 32_000)
14
+ throw new Error('expected must contain the observed event');
15
+ const patch = api.updateCalendarEventRequestSchema.parse(action.args['patch']);
16
+ return withTransaction(database, async (client) => {
17
+ await client.query("SET LOCAL lock_timeout='5s'");
18
+ await client.query("SET LOCAL statement_timeout='10s'");
19
+ const live = await client.query(`SELECT work.id FROM lingxios.agent_work_items work
20
+ JOIN lingxios.agent_action_intents intent ON intent.idempotency_key=$3
21
+ WHERE work.id=$1 AND work.fence=$2 AND work.status='leased' AND work.lease_expires_at>NOW()
22
+ AND work.cancel_requested_at IS NULL AND work.tenant_id=$4 AND work.principal_id=$5
23
+ AND intent.intent->>'workId'=work.id AND intent.intent->'action'->'args'=$6::jsonb
24
+ AND intent.intent->'action'->>'action'='calendar.update'
25
+ AND (intent.intent->>'requestVersion')::integer=jsonb_array_length(work.steer_inputs)+1
26
+ FOR UPDATE OF work`, [work.id, work.fence, action.idempotencyKey, work.tenantId, work.principalId, JSON.stringify(action.args)]);
27
+ if (live.rows.length !== 1)
28
+ throw new Error('calendar update requires the current live action intent');
29
+ await assertCalendarAgent(client, work);
30
+ const permissions = api.createPermissionService(client, { lockDependencies: true });
31
+ await permissions.assertCan({ actorUserId: work.principalId, companyId: work.tenantId,
32
+ action: 'conversation:read', resource: { type: 'conversation', id: work.sessionId } });
33
+ const room = await client.query('SELECT project_id FROM conversations WHERE id=$1 AND company_id=$2 FOR SHARE', [work.sessionId, work.tenantId]);
34
+ const projectId = room.rows[0]?.['project_id'];
35
+ if (typeof projectId !== 'string' || !projectId)
36
+ throw new Error('calendar project scope is unavailable');
37
+ await permissions.assertCan({ actorUserId: work.principalId, companyId: work.tenantId, projectId,
38
+ action: 'calendar:write', resource: { type: 'calendar_event', id: eventId } });
39
+ const current = await client.query('SELECT id FROM calendar_events WHERE id=$1 AND company_id=$2 AND project_id=$3 FOR UPDATE', [eventId, work.tenantId, projectId]);
40
+ if (current.rows.length !== 1)
41
+ throw new Error('calendar event is outside this project');
42
+ let notification;
43
+ const application = new api.CalendarApplication(client, { publish: async (event) => { notification = event; } }, { dispatch: async () => { throw new Error('calendar update cannot dispatch directly'); } });
44
+ const scope = { companyId: work.tenantId, projectId, userId: work.principalId };
45
+ // Compare the complete visible state: native timestamps lose sub-millisecond precision in JSON.
46
+ if (!isDeepStrictEqual(await application.get(scope, eventId), expected))
47
+ throw new Error('calendar event changed; read it again before updating');
48
+ const target = Object.hasOwn(patch, 'targetConversationId') ? patch.targetConversationId : expected['targetConversationId'];
49
+ if (typeof target === 'string')
50
+ await permissions.assertCan({ actorUserId: work.principalId, companyId: work.tenantId, projectId,
51
+ action: 'conversation:write', resource: { type: 'conversation', id: target } });
52
+ const event = await application.update(scope, eventId, patch);
53
+ if (!notification || notification.type !== 'calendar.changed' || notification.kind !== 'event.updated'
54
+ || notification.eventId !== eventId || notification.companyId !== work.tenantId || notification.workspaceId !== projectId)
55
+ throw new Error('calendar update notification is invalid');
56
+ await queueCalendarEvent(client, work, action, { ...notification, actorId: work.agentId });
57
+ return { event, notification: 'queued' };
58
+ });
59
+ }
60
+ export async function assertCalendarAgent(database, work) {
61
+ const { rows } = await database.query(`SELECT p.id FROM participants p
62
+ JOIN im_channel_bindings b ON b.company_id=p.company_id AND b.channel_id=$3
63
+ WHERE p.company_id=$1 AND p.id=$2 AND p.kind='agent' AND p.departed_at IS NULL
64
+ AND p.capabilities @> '["calendar"]'::jsonb AND b.profile->'members' ? p.id
65
+ AND NOT EXISTS(SELECT 1 FROM learning_project_teacher_agents teacher WHERE teacher.company_id=p.company_id AND teacher.agent_id=p.id)
66
+ FOR SHARE OF p,b`, [work.tenantId, work.agentId, work.sessionId]);
67
+ if (rows.length !== 1)
68
+ throw new Error('calendar agent capability or conversation membership was revoked');
69
+ }
70
+ /** Written in the same transaction as the native mutation, including approved writes. */
71
+ export async function queueCalendarEvent(database, work, action, event) {
72
+ await database.query('INSERT INTO lingxios.agent_calendar_outbox(id,work_id,event) VALUES($1,$2,$3::jsonb)', [action.idempotencyKey, work.id, JSON.stringify(event)]);
73
+ }
74
+ export async function flushCalendarEvents(database, services) {
75
+ const api = services.calendar?.writes;
76
+ if (api)
77
+ await flushEventOutbox(database, 'agent_calendar_outbox', event => api.publish(api.CH_CALENDAR_EVENTS, event));
78
+ }
79
+ //# sourceMappingURL=calendar-writes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar-writes.js","sourceRoot":"","sources":["../../../../src/integrations/lingxiloop/calendar-writes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { SqlQueryable } from '../../control-plane/pg-store.js';
2
+ import type { HostAction, WorkItem } from '../../protocol/types.js';
3
+ import type { LingxiLoopServices } from './service-contracts.js';
4
+ export declare const CALENDAR_METHODS: {
5
+ readonly list: readonly ["from", "to"];
6
+ readonly get: readonly ["eventId"];
7
+ };
8
+ export declare function executeCalendar(db: SqlQueryable, services: Pick<LingxiLoopServices, 'calendar' | 'permissionService'>, work: Omit<WorkItem, 'leaseToken'>, action: HostAction): Promise<{
9
+ id: string;
10
+ title: string;
11
+ startAt: string;
12
+ } | {
13
+ events: {
14
+ id: string;
15
+ title: string;
16
+ startAt: string;
17
+ }[];
18
+ truncated: boolean;
19
+ }>;
@@ -0,0 +1,43 @@
1
+ export const CALENDAR_METHODS = { list: ['from', 'to'], get: ['eventId'] };
2
+ export async function executeCalendar(db, services, work, action) {
3
+ const api = services.calendar;
4
+ const method = action.action.slice('calendar.'.length);
5
+ if (!api || !action.action.startsWith('calendar.') || !Object.hasOwn(CALENDAR_METHODS, method))
6
+ throw new Error('unsupported calendar action');
7
+ const allowed = CALENDAR_METHODS[method];
8
+ if (Object.keys(action.args).some(key => !allowed.includes(key)))
9
+ throw new Error('unknown calendar argument');
10
+ if (!work.principalId)
11
+ throw new Error('calendar access requires the original human principal');
12
+ const eventId = action.args['eventId'];
13
+ if (method === 'get' && (typeof eventId !== 'string' || !eventId.trim() || eventId.length > 2000))
14
+ throw new Error('eventId is required');
15
+ let range = {};
16
+ if (method === 'list') {
17
+ range = api.listCalendarEventsQuerySchema.parse(action.args);
18
+ if (!range.from || !range.to || range.to.getTime() < range.from.getTime() || range.to.getTime() - range.from.getTime() > 366 * 86400_000) {
19
+ throw new Error('from and to must define a range of at most 366 days');
20
+ }
21
+ }
22
+ const conversation = { actorUserId: work.principalId, companyId: work.tenantId,
23
+ action: 'conversation:read', resource: { type: 'conversation', id: work.sessionId } };
24
+ await services.permissionService.assertCan(conversation);
25
+ const { rows } = await db.query('SELECT project_id FROM conversations WHERE company_id=$1 AND id=$2', [work.tenantId, work.sessionId]);
26
+ const projectId = rows[0]?.['project_id'];
27
+ if (typeof projectId !== 'string' || !projectId)
28
+ throw new Error('calendar project scope is unavailable');
29
+ const authorization = { actorUserId: work.principalId, companyId: work.tenantId, projectId,
30
+ action: 'calendar:read', resource: method === 'get'
31
+ ? { type: 'calendar_event', id: eventId } : { type: 'project', id: projectId } };
32
+ await services.permissionService.assertCan(authorization);
33
+ const scope = { companyId: work.tenantId, projectId, userId: work.principalId };
34
+ const value = method === 'list' ? await api.calendarApplication.list(scope, range) : await api.calendarApplication.get(scope, eventId);
35
+ await services.permissionService.assertCan(conversation);
36
+ await services.permissionService.assertCan(authorization);
37
+ if (Array.isArray(value))
38
+ return { events: value.slice(0, 100), truncated: value.length > 100 };
39
+ if (value.id !== eventId)
40
+ throw new Error('invalid calendar read result');
41
+ return value;
42
+ }
43
+ //# sourceMappingURL=calendar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar.js","sourceRoot":"","sources":["../../../../src/integrations/lingxiloop/calendar.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { SqlQueryable } from '../../control-plane/pg-store.js';
2
+ import type { LingxiLoopServices } from './service-contracts.js';
3
+ export declare function queueCanvasAssignments(database: SqlQueryable, services: Pick<LingxiLoopServices, 'canvas'>, canvasId: unknown, previous: Record<string, unknown>[]): Promise<void>;
4
+ export declare function queueCanvasReports(database: SqlQueryable, canvasId: string): Promise<void>;
5
+ export declare function flushCanvasEvents(database: SqlQueryable, services: Pick<LingxiLoopServices, 'canvas'>): Promise<void>;
6
+ export declare function queueCanvasActivity(database: SqlQueryable, canvasId: string, activityId: string): Promise<void>;
7
+ export declare function queueCanvasWorkspace(database: SqlQueryable, canvasId: string): Promise<void>;
@@ -0,0 +1,53 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { flushEventOutbox } from './event-outbox.js';
3
+ export async function queueCanvasAssignments(database, services, canvasId, previous) {
4
+ const api = services.canvas.orchestration;
5
+ const canvas = (await database.query('SELECT id,company_id,project_id,conversation_id FROM canvases WHERE id=$1', [canvasId])).rows[0];
6
+ const current = (await database.query('SELECT * FROM canvas_agent_assignments WHERE canvas_id=$1', [canvasId])).rows;
7
+ const dependencies = (await database.query(`SELECT d.assignment_id,p.agent_id FROM canvas_assignment_dependencies d
8
+ JOIN canvas_agent_assignments p ON p.id=d.depends_on_assignment_id WHERE p.canvas_id=$1`, [canvasId])).rows;
9
+ const state = (row) => row && JSON.stringify([row['status'], row['assignment'], row['result'], row['error'], row['work_id']]);
10
+ for (const row of current) {
11
+ if (state(row) === state(previous.find(before => before['id'] === row['id'])))
12
+ continue;
13
+ const event = { type: 'canvas.changed', kind: 'assignment.updated', companyId: String(canvas['company_id']),
14
+ canvasId: String(canvasId), workspaceId: String(canvas['project_id']), conversationId: String(canvas['conversation_id']), timestamp: new Date().toISOString(),
15
+ assignment: api.toAssignment({ ...row, progress_fingerprint: null, no_progress_count: 0 }, dependencies.filter(item => item['assignment_id'] === row['id']).map(item => String(item['agent_id']))) };
16
+ await database.query('INSERT INTO lingxios.agent_canvas_outbox(id,event) VALUES($1,$2::jsonb)', [randomUUID(), JSON.stringify(event)]);
17
+ }
18
+ }
19
+ export async function queueCanvasReports(database, canvasId) {
20
+ const canvas = (await database.query('SELECT company_id,project_id,conversation_id FROM canvases WHERE id=$1', [canvasId])).rows[0];
21
+ const reports = (await database.query('SELECT * FROM canvas_assignment_reports WHERE canvas_id=$1 ORDER BY created_at LIMIT 33', [canvasId])).rows;
22
+ if (reports.length > 32)
23
+ throw new Error('Canvas report notification capacity exceeded');
24
+ const event = { type: 'canvas.changed', kind: 'workspace.updated', companyId: String(canvas['company_id']),
25
+ canvasId, workspaceId: String(canvas['project_id']), conversationId: String(canvas['conversation_id']), timestamp: new Date().toISOString(),
26
+ workspace: { reports: reports.map(row => ({ id: row['id'], canvasId, assignmentId: row['assignment_id'], authorAgentId: row['author_agent_id'],
27
+ executionRole: row['execution_role'], schemaVersion: row['schema_version'], finding: row['finding'], evidenceId: row['evidence_id'],
28
+ sourceEvidenceIds: row['source_evidence_ids'], confidence: Number(row['confidence']), unresolved: row['unresolved'], nextStep: row['next_step'],
29
+ verifiesReportId: row['verifies_report_id'], disconfirmingChecks: row['disconfirming_checks'], verdict: row['verdict'],
30
+ consumedReportIds: row['consumed_report_ids'], conflictResolution: row['conflict_resolution'], createdAt: row['created_at'] })) } };
31
+ await database.query('INSERT INTO lingxios.agent_canvas_outbox(id,event) VALUES($1,$2::jsonb)', [randomUUID(), JSON.stringify(event)]);
32
+ }
33
+ export async function flushCanvasEvents(database, services) {
34
+ const api = services.canvas?.orchestration;
35
+ if (api)
36
+ await flushEventOutbox(database, 'agent_canvas_outbox', event => api.publish(api.CH_CANVAS, event));
37
+ }
38
+ export async function queueCanvasActivity(database, canvasId, activityId) {
39
+ const row = (await database.query(`SELECT a.*,c.company_id,c.project_id,c.conversation_id FROM canvas_activity a
40
+ JOIN canvases c ON c.id=a.canvas_id WHERE a.id=$1 AND a.canvas_id=$2`, [activityId, canvasId])).rows[0];
41
+ const event = { type: 'canvas.changed', kind: 'activity.created', companyId: String(row['company_id']), canvasId,
42
+ workspaceId: String(row['project_id']), conversationId: String(row['conversation_id']), timestamp: new Date().toISOString(),
43
+ activity: { id: row['id'], canvasId, frameId: row['frame_id'], actorId: row['actor_id'], actorKind: row['actor_kind'], action: row['action'], detail: row['detail'], createdAt: row['created_at'] } };
44
+ await database.query('INSERT INTO lingxios.agent_canvas_outbox(id,event) VALUES($1,$2::jsonb)', [randomUUID(), JSON.stringify(event)]);
45
+ }
46
+ export async function queueCanvasWorkspace(database, canvasId) {
47
+ const row = (await database.query('SELECT * FROM canvases WHERE id=$1', [canvasId])).rows[0];
48
+ const event = { type: 'canvas.changed', kind: 'workspace.updated', companyId: String(row['company_id']), canvasId,
49
+ workspaceId: String(row['project_id']), conversationId: String(row['conversation_id']), timestamp: new Date().toISOString(),
50
+ workspace: { id: canvasId, title: row['title'], goal: row['goal'], status: row['status'], summary: row['summary'] } };
51
+ await database.query('INSERT INTO lingxios.agent_canvas_outbox(id,event) VALUES($1,$2::jsonb)', [randomUUID(), JSON.stringify(event)]);
52
+ }
53
+ //# sourceMappingURL=canvas-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas-events.js","sourceRoot":"","sources":["../../../../src/integrations/lingxiloop/canvas-events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { SqlQueryable } from '../../control-plane/pg-store.js';
2
+ import type { WorkItem } from '../../protocol/types.js';
3
+ export declare function assertCanvasSummary(database: SqlQueryable, work: Omit<WorkItem, 'leaseToken'>): Promise<void>;
4
+ /** Called under the current Canvas row lock. Summary tasks retain the originating human request. */
5
+ export declare function reconcileCanvasSummary(database: SqlQueryable, canvasId: string): Promise<void>;
@@ -0,0 +1,52 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { queueCanvasWorkspace } from './canvas-events.js';
3
+ export async function assertCanvasSummary(database, work) {
4
+ const { rows } = await database.query(`SELECT c.id FROM canvases c JOIN lingxios.agent_work_items w ON w.id=$1
5
+ WHERE c.id=$2 AND c.company_id=$3 AND c.conversation_id=$4 AND c.status='summarizing'
6
+ AND w.kind='canvas_summary' AND w.meta->>'executionRole'='reporter' AND w.agent_id=$5 AND w.principal_id=$6
7
+ AND w.meta->>'canvasId'=c.id AND NOT EXISTS(SELECT 1 FROM canvas_agent_assignments a
8
+ WHERE a.canvas_id=c.id AND a.status NOT IN ('completed','failed','cancelled'))`, [work.id, work.meta?.['canvasId'], work.tenantId, work.sessionId, work.agentId, work.principalId]);
9
+ if (rows.length !== 1)
10
+ throw new Error('Canvas reporter work is no longer runnable');
11
+ }
12
+ /** Called under the current Canvas row lock. Summary tasks retain the originating human request. */
13
+ export async function reconcileCanvasSummary(database, canvasId) {
14
+ const canvas = (await database.query('SELECT * FROM canvases WHERE id=$1', [canvasId])).rows[0];
15
+ if (canvas['status'] === 'summarizing') {
16
+ const summary = (await database.query(`SELECT w.id,w.status,w.goal_outcome,w.result_text,w.error,
17
+ EXISTS(SELECT 1 FROM canvas_assignment_reports r JOIN evidence_records e ON e.id=r.evidence_id
18
+ WHERE r.canvas_id=$1 AND r.company_id=w.tenant_id AND r.execution_role='reporter' AND r.author_agent_id=w.agent_id
19
+ AND e.data->>'workId'=w.id AND e.data->>'requestVersion'=(jsonb_array_length(w.steer_inputs)+1)::text) AS report_ready
20
+ FROM lingxios.agent_work_items w WHERE w.kind='canvas_summary' AND w.tenant_id=$2 AND w.meta->>'canvasId'=$1
21
+ ORDER BY w.created_at DESC LIMIT 1 FOR UPDATE OF w`, [canvasId, canvas['company_id']])).rows[0];
22
+ if (!summary || !['completed', 'failed', 'cancelled'].includes(String(summary['status'])))
23
+ return;
24
+ const outcome = summary['goal_outcome'];
25
+ if (outcome?.status === 'awaiting_input' || outcome?.status === 'awaiting_approval')
26
+ return;
27
+ const status = summary['status'] === 'completed' && summary['report_ready'] ? 'completed' : summary['status'] === 'cancelled' ? 'stopped' : 'failed';
28
+ await database.query('UPDATE canvases SET status=$2,summary=$3,completed_at=NOW(),updated_at=NOW() WHERE id=$1', [canvasId, status, summary['result_text'] ?? summary['error'] ?? 'Canvas reporter ended without a persisted report']);
29
+ await queueCanvasWorkspace(database, canvasId);
30
+ return;
31
+ }
32
+ if (canvas['status'] !== 'active')
33
+ return;
34
+ const unfinished = await database.query("SELECT 1 FROM canvas_agent_assignments WHERE canvas_id=$1 AND status NOT IN ('completed','failed','cancelled') LIMIT 1", [canvasId]);
35
+ if (unfinished.rows.length)
36
+ return;
37
+ const origin = (await database.query(`SELECT parent.* FROM canvas_agent_assignments a
38
+ JOIN lingxios.agent_work_items child ON child.id=a.work_id AND child.kind='canvas_worker' AND child.meta->>'assignmentId'=a.id
39
+ JOIN lingxios.agent_work_items parent ON parent.id=child.meta->>'parentWorkId'
40
+ AND parent.tenant_id=child.tenant_id AND parent.principal_id=child.principal_id AND parent.session_id=child.session_id
41
+ WHERE a.canvas_id=$1 AND child.tenant_id=$2 ORDER BY child.created_at,child.id LIMIT 1`, [canvasId, canvas['company_id']])).rows[0];
42
+ if (!origin || typeof origin['meta']?.['text'] !== 'string')
43
+ return;
44
+ const id = 'canvas-summary-' + createHash('sha256').update(canvasId).digest('hex').slice(0, 24);
45
+ const meta = origin['meta'];
46
+ await database.query(`INSERT INTO lingxios.agent_work_items(id,tenant_id,agent_id,session_id,principal_id,thread_id,kind,lane,trigger_ref,priority,meta,steer_inputs)
47
+ VALUES($1,$2,$3,$4,$5,$6,'canvas_summary','collaboration',$7,200,$8::jsonb,$9::jsonb)`, [id, origin['tenant_id'], origin['agent_id'], origin['session_id'], origin['principal_id'], origin['thread_id'], origin['trigger_ref'],
48
+ JSON.stringify({ text: meta['text'], authorName: meta['authorName'], attachments: meta['attachments'], canvasId, executionRole: 'reporter', parentWorkId: origin['id'] }), JSON.stringify(origin['steer_inputs'])]);
49
+ await database.query("UPDATE canvases SET status='summarizing',updated_at=NOW() WHERE id=$1", [canvasId]);
50
+ await queueCanvasWorkspace(database, canvasId);
51
+ }
52
+ //# sourceMappingURL=canvas-summary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas-summary.js","sourceRoot":"","sources":["../../../../src/integrations/lingxiloop/canvas-summary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { SqlQueryable } from '../../control-plane/pg-store.js';
2
+ import type { WorkItem } from '../../protocol/types.js';
3
+ import type { LingxiLoopServices } from './service-contracts.js';
4
+ /** A persisted report records an agent finding, not proof that the user's goal is satisfied. */
5
+ export declare function submitCanvasWorkReport(db: SqlQueryable, services: Pick<LingxiLoopServices, 'canvas'>, work: Omit<WorkItem, 'leaseToken'>, args: Record<string, unknown>, canvasId: string, projectId: string, requestVersion: number, assignmentVersion: number): Promise<{
6
+ reportId: string;
7
+ assignmentId: unknown;
8
+ evidenceId: string;
9
+ sourceEvidenceIds: string[];
10
+ verdict: string | null;
11
+ unresolved: string[];
12
+ }>;