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,38 @@
1
+ export const DOCUMENT_METHODS = { list: [], read: ['documentId'] };
2
+ export async function executeDocument(db, services, work, action) {
3
+ const api = services.documents;
4
+ const method = action.action.slice('documents.'.length);
5
+ if (!api || !action.action.startsWith('documents.') || !Object.hasOwn(DOCUMENT_METHODS, method))
6
+ throw new Error('unsupported document action');
7
+ const allowed = DOCUMENT_METHODS[method];
8
+ if (Object.keys(action.args).some(key => !allowed.includes(key)))
9
+ throw new Error('unknown document argument');
10
+ if (!work.principalId)
11
+ throw new Error('document access requires the original human principal');
12
+ const documentId = action.args['documentId'];
13
+ if (method === 'read' && (typeof documentId !== 'string' || !documentId.trim() || documentId.length > 2000))
14
+ throw new Error('documentId is required');
15
+ await services.permissionService.assertCan({ actorUserId: work.principalId, companyId: work.tenantId,
16
+ action: 'conversation:read', resource: { type: 'conversation', id: work.sessionId } });
17
+ const { rows } = await db.query('SELECT project_id FROM conversations WHERE company_id=$1 AND id=$2', [work.tenantId, work.sessionId]);
18
+ const projectId = rows[0]?.['project_id'];
19
+ if (typeof projectId !== 'string' || !projectId)
20
+ throw new Error('document project scope is unavailable');
21
+ const authorization = { actorUserId: work.principalId, companyId: work.tenantId, projectId,
22
+ action: 'document:read', resource: method === 'read'
23
+ ? { type: 'document', id: documentId } : { type: 'project', id: projectId } };
24
+ await services.permissionService.assertCan(authorization);
25
+ const scope = { companyId: work.tenantId, projectId, userId: work.principalId };
26
+ if (method === 'list') {
27
+ const documents = await api.listAgentDocuments(scope);
28
+ await services.permissionService.assertCan(authorization);
29
+ return { documents: documents.slice(0, 100), truncated: documents.length > 100 };
30
+ }
31
+ const document = await api.readAgentDocument(scope, documentId);
32
+ // Native Agent readers scope their lookup but do not authorize the human.
33
+ await services.permissionService.assertCan(authorization);
34
+ if (document.id !== documentId || typeof document.body !== 'string')
35
+ throw new Error('invalid document read result');
36
+ return { ...document, body: document.body.slice(0, 64_000), bodyTruncated: document.body.length > 64_000 };
37
+ }
38
+ //# sourceMappingURL=documents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"documents.js","sourceRoot":"","sources":["../../../../src/integrations/lingxiloop/documents.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { SqlQueryable } from '../../control-plane/pg-store.js';
2
+ type Table = 'agent_calendar_outbox' | 'agent_canvas_outbox' | 'agent_document_outbox';
3
+ /** Native Redis publishing is not abortable. Bound outstanding commands while durable rows own retries. */
4
+ export declare function flushEventOutbox(database: SqlQueryable, table: Table, publish: (event: unknown) => Promise<void>): Promise<void>;
5
+ export {};
@@ -0,0 +1,47 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { createLogger } from '../../logging.js';
3
+ const pending = new WeakMap();
4
+ /** Native Redis publishing is not abortable. Bound outstanding commands while durable rows own retries. */
5
+ export async function flushEventOutbox(database, table, publish) {
6
+ let commands = pending.get(database);
7
+ if (!commands) {
8
+ commands = new Map();
9
+ pending.set(database, commands);
10
+ }
11
+ if (commands.has(table))
12
+ return;
13
+ const operation = publishNext(database, table, publish).catch(() => {
14
+ createLogger().warn('native notification acknowledgement failed; the durable outbox will retry', { table });
15
+ }).finally(() => commands.delete(table));
16
+ commands.set(table, operation);
17
+ let timer;
18
+ try {
19
+ await Promise.race([operation, new Promise(resolve => { timer = setTimeout(resolve, 1000); timer.unref(); })]);
20
+ }
21
+ finally {
22
+ if (timer)
23
+ clearTimeout(timer);
24
+ }
25
+ }
26
+ async function publishNext(database, table, publish) {
27
+ const token = randomUUID();
28
+ // table is a package-owned union, never a resource or model-supplied identifier.
29
+ const { rows } = await database.query(`WITH candidate AS (
30
+ SELECT id FROM lingxios.${table} WHERE delivered_at IS NULL AND available_at<=NOW()
31
+ ORDER BY available_at,id LIMIT 1 FOR UPDATE SKIP LOCKED)
32
+ UPDATE lingxios.${table} outbox SET claim_token=$1,available_at=NOW()+INTERVAL '60 seconds',attempts=LEAST(attempts+1,30)
33
+ FROM candidate WHERE outbox.id=candidate.id RETURNING outbox.id,outbox.event`, [token]);
34
+ const row = rows[0];
35
+ if (!row)
36
+ return;
37
+ try {
38
+ await publish(row['event']);
39
+ await database.query(`UPDATE lingxios.${table} SET delivered_at=NOW(),claim_token=NULL WHERE id=$1 AND claim_token=$2`, [row['id'], token]);
40
+ }
41
+ catch {
42
+ await database.query(`UPDATE lingxios.${table} SET claim_token=NULL,
43
+ available_at=NOW()+LEAST(300,5*power(2,LEAST(attempts-1,6)))*INTERVAL '1 second'
44
+ WHERE id=$1 AND claim_token=$2`, [row['id'], token]);
45
+ }
46
+ }
47
+ //# sourceMappingURL=event-outbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-outbox.js","sourceRoot":"","sources":["../../../../src/integrations/lingxiloop/event-outbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAG/C,MAAM,OAAO,GAAG,IAAI,OAAO,EAA2C,CAAA;AAEtE,2GAA2G;AAC3G,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAsB,EAAE,KAAY,EAAE,OAA0C;IACrH,IAAI,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IACpC,IAAI,CAAC,QAAQ,EAAE,CAAC;QAAC,QAAQ,GAAG,IAAI,GAAG,EAAE,CAAC;QAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAAC,CAAC;IACxE,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,OAAM;IAC/B,MAAM,SAAS,GAAG,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;QACjE,YAAY,EAAE,CAAC,IAAI,CAAC,2EAA2E,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;IAC7G,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;IACxC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;IAC9B,IAAI,KAAgD,CAAA;IACpD,IAAI,CAAC;QAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE,GAAG,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAAC,CAAC;YACnH,CAAC;QAAC,IAAI,KAAK;YAAE,YAAY,CAAC,KAAK,CAAC,CAAA;IAAC,CAAC;AAC5C,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,QAAsB,EAAE,KAAY,EAAE,OAA0C;IACzG,MAAM,KAAK,GAAG,UAAU,EAAE,CAAA;IAC1B,iFAAiF;IACjF,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC;8BACV,KAAK;;sBAEb,KAAK;iFACsD,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;IACzF,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;IACnB,IAAI,CAAC,GAAG;QAAE,OAAM;IAChB,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAA;QAC3B,MAAM,QAAQ,CAAC,KAAK,CAAC,mBAAmB,KAAK,yEAAyE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAA;IAC7I,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,QAAQ,CAAC,KAAK,CAAC,mBAAmB,KAAK;;qCAEZ,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAA;IACxD,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { createLingxiLoop, type LingxiLoopOptions } from './app.js';
2
+ export { releaseVersions } from '../../versions.js';
3
+ export type { LingxiLoopServices, KnowledgeServices, NativeWork, NativeMessage } from './service-contracts.js';
@@ -0,0 +1,3 @@
1
+ export { createLingxiLoop } from './app.js';
2
+ export { releaseVersions } from '../../versions.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/integrations/lingxiloop/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAA0B,MAAM,UAAU,CAAA;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA"}
@@ -0,0 +1,13 @@
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
+ export declare function readAttempts(database: SqlPool, services: Pick<LingxiLoopServices, 'learning' | 'permissionService'>, work: Omit<WorkItem, 'leaseToken'>, action: HostAction): Promise<{
5
+ attempts: Record<string, unknown>[];
6
+ truncated: boolean;
7
+ } | {
8
+ evidence: Record<string, unknown> | undefined;
9
+ evaluations: Record<string, unknown>[];
10
+ evaluationsTruncated: boolean;
11
+ attempts?: never;
12
+ truncated?: never;
13
+ }>;
@@ -0,0 +1,58 @@
1
+ import { withTransaction } from '../../control-plane/pg-store.js';
2
+ export async function readAttempts(database, services, work, action) {
3
+ const detail = action.action === 'learning.get_attempt';
4
+ if (!services.learning || !work.principalId || (!detail && action.action !== 'learning.list_attempts'))
5
+ throw new Error('learning attempt services and principal are required');
6
+ const allowed = detail ? ['attemptId'] : ['activityId', 'missionStepId'];
7
+ if (Object.keys(action.args).some(key => !allowed.includes(key)))
8
+ throw new Error('unknown attempt read argument');
9
+ const id = (value) => {
10
+ if (value === undefined)
11
+ return undefined;
12
+ if (typeof value !== 'string' || !value.trim() || value.length > 200)
13
+ throw new Error('attempt read identifiers must contain 1 to 200 characters');
14
+ return value.trim();
15
+ };
16
+ const attemptId = id(action.args['attemptId']), activityId = id(action.args['activityId']), missionStepId = id(action.args['missionStepId']);
17
+ if (detail && !attemptId)
18
+ throw new Error('attemptId is required');
19
+ if (activityId && missionStepId)
20
+ throw new Error('filter by activityId or missionStepId, not both');
21
+ await services.permissionService.assertCan({ actorUserId: work.principalId, companyId: work.tenantId,
22
+ action: 'learning:read', resource: { type: 'conversation', id: work.sessionId } });
23
+ const api = services.learning;
24
+ return withTransaction(database, async (client) => {
25
+ await client.query('SET TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ ONLY');
26
+ await client.query("SET LOCAL statement_timeout='10s'");
27
+ const room = await api.findLearningRoomState(client, { companyId: work.tenantId, channelId: work.sessionId });
28
+ if (!room || room.companyId !== work.tenantId)
29
+ throw new Error('conversation is not bound to a learning project');
30
+ await api.createPermissionService(client).assertCan({ actorUserId: work.principalId, companyId: work.tenantId,
31
+ action: 'learning:read', resource: { type: 'conversation', id: work.sessionId } });
32
+ const { rows } = await client.query(`SELECT attempt.id,attempt.activity_id,attempt.mission_step_id,attempt.assistance,
33
+ attempt.status,attempt.submitted_at,attempt.evidence_id
34
+ FROM learning_attempts attempt JOIN participants learner
35
+ ON learner.id=attempt.learner_id AND learner.company_id=attempt.company_id
36
+ WHERE attempt.company_id=$1 AND attempt.project_id=$2 AND attempt.learner_id=$3
37
+ AND learner.kind='human' AND learner.departed_at IS NULL
38
+ AND ($4::text IS NULL OR attempt.id=$4)
39
+ AND ($5::text IS NULL OR attempt.activity_id=$5)
40
+ AND ($6::text IS NULL OR attempt.mission_step_id=$6)
41
+ ORDER BY attempt.submitted_at DESC,attempt.id DESC LIMIT 101`, [work.tenantId, room.projectId, work.principalId, attemptId ?? null, activityId ?? null, missionStepId ?? null]);
42
+ if (!detail)
43
+ return { attempts: rows.slice(0, 100), truncated: rows.length > 100 };
44
+ const attempt = rows[0];
45
+ if (!attempt)
46
+ throw new Error('attempt not found for this principal in this project');
47
+ const evidence = await client.query(`SELECT id,data,created_by_type,created_by_id,created_at FROM evidence_records
48
+ WHERE id=$1 AND company_id=$2 AND project_id=$3`, [attempt['evidence_id'], work.tenantId, room.projectId]);
49
+ if (evidence.rows.length !== 1)
50
+ throw new Error('attempt evidence not found in this project');
51
+ const evaluations = await client.query(`SELECT id,demonstrated_level,confidence,rubric_results,feedback,evaluator_id,
52
+ evaluator_kind,status,source_evidence_id,verifier_evidence_id,created_at
53
+ FROM learning_evaluations WHERE attempt_id=$1 AND company_id=$2 AND project_id=$3
54
+ ORDER BY created_at DESC,id DESC LIMIT 101`, [attemptId, work.tenantId, room.projectId]);
55
+ return { ...attempt, evidence: evidence.rows[0], evaluations: evaluations.rows.slice(0, 100), evaluationsTruncated: evaluations.rows.length > 100 };
56
+ });
57
+ }
58
+ //# sourceMappingURL=learning-attempts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learning-attempts.js","sourceRoot":"","sources":["../../../../src/integrations/lingxiloop/learning-attempts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
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
+ export declare function proposeEvaluation(database: SqlPool, services: Pick<LingxiLoopServices, 'learning' | 'permissionService'>, work: Omit<WorkItem, 'leaseToken'>, action: HostAction): Promise<{
5
+ evaluationId: string;
6
+ status: "ACCEPTED" | "PENDING";
7
+ decisions: unknown[];
8
+ }>;
@@ -0,0 +1,64 @@
1
+ import { withTransaction } from '../../control-plane/pg-store.js';
2
+ import { teacherTransaction } from './teacher.js';
3
+ export async function proposeEvaluation(database, services, work, action) {
4
+ const api = services.learning;
5
+ if (!api || !work.principalId || action.action !== 'learning.propose_evaluation')
6
+ throw new Error('learning evaluation services and principal are required');
7
+ if (Object.keys(action.args).some(key => !['attemptId', 'demonstratedLevel', 'confidence', 'rubricResults', 'feedback', 'sourceEvidenceId', 'verifierEvidenceId'].includes(key)))
8
+ throw new Error('unknown evaluation argument');
9
+ const text = (value, max) => {
10
+ if (typeof value !== 'string' || !value.trim() || value.length > max)
11
+ throw new Error(`evaluation text must contain 1 to ${max} characters`);
12
+ return value.trim();
13
+ };
14
+ const attemptId = text(action.args['attemptId'], 200);
15
+ const demonstratedLevel = action.args['demonstratedLevel'], confidence = action.args['confidence'];
16
+ if (typeof demonstratedLevel !== 'number' || !Number.isInteger(demonstratedLevel) || demonstratedLevel < 0 || demonstratedLevel > 4)
17
+ throw new Error('demonstratedLevel must be an integer from 0 to 4');
18
+ if (typeof confidence !== 'number' || !Number.isFinite(confidence) || confidence < 0 || confidence > 1)
19
+ throw new Error('confidence must be from 0 to 1');
20
+ const rubricResults = api.learningScoreBreakdownSchema.parse(action.args['rubricResults']);
21
+ const feedback = action.args['feedback'] === undefined ? undefined : text(action.args['feedback'], 10000);
22
+ const sourceEvidenceId = action.args['sourceEvidenceId'] === undefined ? undefined : text(action.args['sourceEvidenceId'], 200);
23
+ const verifierEvidenceId = action.args['verifierEvidenceId'] === undefined ? undefined : text(action.args['verifierEvidenceId'], 200);
24
+ if (verifierEvidenceId && !sourceEvidenceId)
25
+ throw new Error('verifier evidence requires source evidence');
26
+ await services.permissionService.assertCan({ actorUserId: work.principalId, companyId: work.tenantId,
27
+ action: 'learning:submit', resource: { type: 'conversation', id: work.sessionId } });
28
+ const metrics = [];
29
+ const result = await withTransaction(database, async (client) => {
30
+ // Native evaluation reads state before taking its state locks; concurrent changes must abort this snapshot.
31
+ await client.query('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE');
32
+ await client.query("SET LOCAL statement_timeout='10s'");
33
+ const room = await api.findLearningRoomState(client, { companyId: work.tenantId, channelId: work.sessionId });
34
+ if (!room || room.companyId !== work.tenantId)
35
+ throw new Error('conversation is not bound to a learning project');
36
+ await api.createPermissionService(client, { lockDependencies: true }).assertCan({ actorUserId: work.principalId, companyId: work.tenantId,
37
+ action: 'learning:submit', resource: { type: 'conversation', id: work.sessionId } });
38
+ const attempt = await client.query(`SELECT attempt.id FROM learning_attempts attempt
39
+ JOIN participants learner ON learner.id=attempt.learner_id AND learner.company_id=attempt.company_id
40
+ WHERE attempt.id=$1 AND attempt.company_id=$2 AND attempt.project_id=$3 AND attempt.learner_id=$4
41
+ AND learner.kind='human' AND learner.departed_at IS NULL FOR UPDATE OF attempt`, [attemptId, work.tenantId, room.projectId, work.principalId]);
42
+ if (attempt.rows.length !== 1)
43
+ throw new Error('attempt must belong to the persisted human principal in this project');
44
+ for (const evidenceId of [sourceEvidenceId, verifierEvidenceId]) {
45
+ if (!evidenceId)
46
+ continue;
47
+ const evidence = await client.query('SELECT id FROM evidence_records WHERE id=$1 AND company_id=$2 AND project_id=$3', [evidenceId, work.tenantId, room.projectId]);
48
+ if (evidence.rows.length !== 1)
49
+ throw new Error('evaluation evidence is outside this project');
50
+ }
51
+ return api.proposeLearningEvaluation(client, teacherTransaction(client), (name, labels) => {
52
+ if (name !== 'learning.state.changed' && name !== 'learning.evaluation.proposed')
53
+ throw new Error('unexpected evaluation metric');
54
+ if (metrics.length >= 1000)
55
+ throw new Error('evaluation exceeds metric limit');
56
+ metrics.push({ name, ...(labels ? { labels } : {}) });
57
+ }, { companyId: work.tenantId, channelId: work.sessionId, agentId: work.agentId, attemptId, demonstratedLevel, confidence, rubricResults,
58
+ ...(feedback === undefined ? {} : { feedback }), ...(sourceEvidenceId ? { sourceEvidenceId } : {}), ...(verifierEvidenceId ? { verifierEvidenceId } : {}) });
59
+ });
60
+ for (const metric of metrics)
61
+ api.inc(metric.name, metric.labels);
62
+ return result;
63
+ }
64
+ //# sourceMappingURL=learning-evaluation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learning-evaluation.js","sourceRoot":"","sources":["../../../../src/integrations/lingxiloop/learning-evaluation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
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
+ export declare function recordAttempt(database: SqlPool, services: Pick<LingxiLoopServices, 'learning' | 'permissionService' | 'wukongClient'>, work: Omit<WorkItem, 'leaseToken'>, action: HostAction, channelType: number): Promise<{
5
+ id: string;
6
+ learnerId: string;
7
+ }>;
@@ -0,0 +1,88 @@
1
+ import { withTransaction } from '../../control-plane/pg-store.js';
2
+ import { teacherTransaction } from './teacher.js';
3
+ export async function recordAttempt(database, services, work, action, channelType) {
4
+ const api = services.learning;
5
+ if (!api || !work.principalId || action.action !== 'learning.record_attempt')
6
+ throw new Error('learning evidence services and principal are required');
7
+ if (Object.keys(action.args).some(key => !['activityId', 'missionStepId', 'evidenceClientMsgNos', 'documentIds', 'canvasFrameIds', 'assistance'].includes(key)))
8
+ throw new Error('unknown attempt argument');
9
+ const id = (value) => {
10
+ if (typeof value !== 'string' || !value.trim() || value.length > 2000)
11
+ throw new Error('evidence identifiers must contain 1 to 2000 characters');
12
+ return value.trim();
13
+ };
14
+ const activityId = action.args['activityId'] === undefined ? undefined : id(action.args['activityId']);
15
+ const missionStepId = action.args['missionStepId'] === undefined ? undefined : id(action.args['missionStepId']);
16
+ if (Boolean(activityId) === Boolean(missionStepId))
17
+ throw new Error('exactly one activityId or missionStepId is required');
18
+ const refs = (key) => {
19
+ const value = action.args[key] === undefined ? [] : action.args[key];
20
+ if (!Array.isArray(value) || value.length > 20)
21
+ throw new Error('each evidence list is limited to 20 references');
22
+ const result = value.map(id);
23
+ if (new Set(result).size !== result.length)
24
+ throw new Error('duplicate evidence reference');
25
+ return result;
26
+ };
27
+ const evidenceClientMsgNos = refs('evidenceClientMsgNos'), documentIds = refs('documentIds'), canvasFrameIds = refs('canvasFrameIds');
28
+ if (!evidenceClientMsgNos.length && !documentIds.length && !canvasFrameIds.length)
29
+ throw new Error('at least one evidence reference is required');
30
+ const assistance = action.args['assistance'] === undefined ? 'NONE' : action.args['assistance'];
31
+ if (assistance !== 'NONE' && assistance !== 'HINT' && assistance !== 'GUIDED')
32
+ throw new Error('invalid assistance');
33
+ if (channelType !== 1 && channelType !== 2)
34
+ throw new Error('invalid evidence channel type');
35
+ await services.permissionService.assertCan({ actorUserId: work.principalId, companyId: work.tenantId,
36
+ action: 'learning:submit', resource: { type: 'conversation', id: work.sessionId } });
37
+ const messages = evidenceClientMsgNos.length ? await services.wukongClient().syncMessages(work.sessionId, channelType, 100, work.agentId) : [];
38
+ const scopedMessages = evidenceClientMsgNos.map(ref => {
39
+ const message = messages.find(item => item.clientMsgNo === ref && item.channelId === work.sessionId && item.channelType === channelType);
40
+ if (!message || message.fromUid !== work.principalId || message.payload.refs?.agentId)
41
+ throw new Error('evidence message must be authored by the persisted human principal');
42
+ return { clientMsgNo: ref, fromUid: work.principalId, authoredByAgent: false };
43
+ });
44
+ let metric;
45
+ const result = await withTransaction(database, async (client) => {
46
+ // Author/revision checks and native evidence reads must observe the same versions.
47
+ await client.query('SET TRANSACTION ISOLATION LEVEL REPEATABLE READ');
48
+ await client.query("SET LOCAL statement_timeout='10s'");
49
+ const room = await api.findLearningRoomState(client, { companyId: work.tenantId, channelId: work.sessionId });
50
+ if (!room || room.companyId !== work.tenantId)
51
+ throw new Error('conversation is not bound to a learning project');
52
+ await api.createPermissionService(client, { lockDependencies: true }).assertCan({ actorUserId: work.principalId, companyId: work.tenantId,
53
+ action: 'learning:submit', resource: { type: 'conversation', id: work.sessionId } });
54
+ const human = await client.query("SELECT 1 FROM participants WHERE company_id=$1 AND id=$2 AND kind='human' AND departed_at IS NULL", [work.tenantId, work.principalId]);
55
+ if (human.rows.length !== 1)
56
+ throw new Error('evidence principal is not an active human');
57
+ for (const documentId of documentIds) {
58
+ const evidence = await api.findLearningDocumentEvidence(client, { companyId: work.tenantId, projectId: room.projectId, documentId });
59
+ if (!evidence || evidence.authorId !== work.principalId)
60
+ throw new Error('document evidence must belong to the persisted human principal in this project');
61
+ }
62
+ for (const frameId of canvasFrameIds) {
63
+ const evidence = await api.findLearningCanvasEvidence(client, { companyId: work.tenantId, projectId: room.projectId, frameId });
64
+ if (!evidence || evidence.authorId !== work.principalId)
65
+ throw new Error('Canvas evidence must belong to the persisted human principal in this project');
66
+ }
67
+ const recorded = await api.recordLearningAttempt(client, teacherTransaction(client), {
68
+ syncMessages: async (input) => {
69
+ if (input.channelId !== work.sessionId || input.channelType !== channelType || input.loginUid !== work.agentId)
70
+ throw new Error('native evidence scope changed');
71
+ return scopedMessages;
72
+ },
73
+ metric: (name, labels) => {
74
+ if (name !== 'learning.attempt.accepted')
75
+ throw new Error('unexpected native evidence metric');
76
+ metric = labels ? { labels } : {};
77
+ },
78
+ }, { companyId: work.tenantId, channelId: work.sessionId, agentId: work.agentId,
79
+ ...(activityId ? { activityId } : { missionStepId: missionStepId }), evidenceClientMsgNos, documentIds, canvasFrameIds, assistance });
80
+ if (recorded.learnerId !== work.principalId || !recorded.id)
81
+ throw new Error('recorded attempt does not match the authorized learner');
82
+ return recorded;
83
+ });
84
+ if (metric)
85
+ api.inc('learning.attempt.accepted', metric.labels);
86
+ return result;
87
+ }
88
+ //# sourceMappingURL=learning-evidence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learning-evidence.js","sourceRoot":"","sources":["../../../../src/integrations/lingxiloop/learning-evidence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
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 } from './service-contracts.js';
4
+ type Services = Pick<LingxiLoopServices, 'learning' | 'permissionService' | 'wukongClient'>;
5
+ export declare function startMission(database: SqlPool, services: Services, work: Omit<WorkItem, 'leaseToken'>, action: HostAction, channelType: number): Promise<{
6
+ id: string;
7
+ projectId: string;
8
+ learnerId: string;
9
+ conversationId: string;
10
+ triggerClientMsgNo: string;
11
+ goal: string;
12
+ successCriteria: string;
13
+ kind: "STUDY" | "RESEARCH" | "PROJECT";
14
+ coordinatorAgentId: string;
15
+ status: string;
16
+ }>;
17
+ export declare function assertMissionCoordinatorWork(database: SqlQueryable, services: Pick<LingxiLoopServices, 'learning' | 'permissionService'>, work: Omit<WorkItem, 'leaseToken'>): Promise<string>;
18
+ export {};
@@ -0,0 +1,95 @@
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ import { withTransaction } from '../../control-plane/pg-store.js';
3
+ export async function startMission(database, services, work, action, channelType) {
4
+ const api = services.learning;
5
+ if (!api || !work.principalId || action.action !== 'learning.start_mission')
6
+ throw new Error('learning Mission services and principal are required');
7
+ if (Object.keys(action.args).some(key => !['goal', 'successCriteria', 'missionKind', 'sourceClientMsgNo', 'explicit'].includes(key)))
8
+ throw new Error('unknown Mission argument');
9
+ const required = (key) => {
10
+ const value = action.args[key];
11
+ if (typeof value !== 'string' || !value.trim() || value.length > 10_000)
12
+ throw new Error(`${key} must contain 1 to 10000 characters`);
13
+ return value.trim();
14
+ };
15
+ const goal = required('goal'), successCriteria = required('successCriteria');
16
+ const explicit = action.args['explicit'], requestedKind = action.args['missionKind'];
17
+ if (explicit !== undefined && typeof explicit !== 'boolean')
18
+ throw new Error('explicit must be boolean');
19
+ if (requestedKind !== undefined && requestedKind !== 'STUDY' && requestedKind !== 'RESEARCH' && requestedKind !== 'PROJECT')
20
+ throw new Error('invalid Mission kind');
21
+ const source = action.args['sourceClientMsgNo'] === undefined ? work.triggerRef : required('sourceClientMsgNo');
22
+ await services.permissionService.assertCan({ actorUserId: work.principalId, companyId: work.tenantId,
23
+ action: 'learning:submit', resource: { type: 'conversation', id: work.sessionId } });
24
+ const room = await api.findLearningRoomState(database, { companyId: work.tenantId, channelId: work.sessionId });
25
+ if (!room || room.companyId !== work.tenantId)
26
+ throw new Error('conversation is not bound to a learning project');
27
+ if (room.purpose !== 'study' && explicit !== true)
28
+ throw new Error('Mission creation outside a study room requires an explicit learner request');
29
+ if (channelType !== 1 && channelType !== 2)
30
+ throw new Error('invalid Mission channel type');
31
+ const messages = await services.wukongClient().syncMessages(work.sessionId, channelType, 100, work.agentId);
32
+ const trigger = messages.find(message => message.clientMsgNo === source && message.channelId === work.sessionId && message.channelType === channelType);
33
+ if (!trigger || trigger.fromUid !== work.principalId || trigger.payload.refs?.agentId || trigger.payload.kind !== 'text' || typeof trigger.payload.body !== 'string')
34
+ throw new Error('Mission source must be the persisted principal’s committed text message in this conversation');
35
+ const { rows: humans } = await database.query("SELECT name FROM participants WHERE company_id=$1 AND id=$2 AND kind='human' AND departed_at IS NULL", [work.tenantId, trigger.fromUid]);
36
+ if (humans.length !== 1)
37
+ throw new Error('Mission source author is not an active human');
38
+ await services.permissionService.assertCan({ actorUserId: trigger.fromUid, companyId: work.tenantId,
39
+ action: 'learning:submit', resource: { type: 'project', id: room.projectId } });
40
+ const kind = requestedKind ?? (room.purpose === 'lab' ? 'PROJECT' : 'STUDY');
41
+ const result = await withTransaction(database, async (client) => {
42
+ const current = await api.findLearningRoomState(client, { companyId: work.tenantId, channelId: work.sessionId });
43
+ if (!current || current.projectId !== room.projectId || current.courseId !== room.courseId || current.purpose !== room.purpose)
44
+ throw new Error('Mission room binding changed');
45
+ const coordinatorAgentId = await api.findEligibleLearningMissionCoordinator(client, {
46
+ companyId: room.companyId, projectId: room.projectId, channelId: work.sessionId,
47
+ preferredPreset: kind === 'PROJECT' ? 'forge' : kind === 'RESEARCH' ? 'scout' : 'nova', currentAgentId: work.agentId,
48
+ });
49
+ if (!coordinatorAgentId)
50
+ throw new Error('no eligible Mission coordinator is available in this conversation');
51
+ const stored = await api.upsertLearningMission(client, { id: randomUUID(), companyId: room.companyId, projectId: room.projectId,
52
+ learnerId: trigger.fromUid, channelId: work.sessionId, triggerClientMsgNo: source, goal, successCriteria, kind, coordinatorAgentId, createdBy: work.agentId });
53
+ const mission = await api.findLearningMission(client, room.companyId, room.projectId, stored.id);
54
+ if (!mission || mission.projectId !== room.projectId || mission.learnerId !== trigger.fromUid || mission.conversationId !== work.sessionId
55
+ || mission.triggerClientMsgNo !== source || stored.inserted && mission.coordinatorAgentId !== coordinatorAgentId)
56
+ throw new Error('stored Mission does not match its authorized source');
57
+ if (stored.inserted && coordinatorAgentId !== work.agentId) {
58
+ const id = 'mission-coordinator-' + createHash('sha256').update(JSON.stringify([work.tenantId, mission.id])).digest('hex');
59
+ await client.query(`INSERT INTO lingxios.agent_work_items(id,tenant_id,agent_id,session_id,principal_id,thread_id,kind,lane,trigger_ref,priority,meta)
60
+ VALUES($1,$2,$3,$4,$5,$6,'mission_coordinator','collaboration',$7,190,$8::jsonb)`, [id, work.tenantId, coordinatorAgentId, work.sessionId, trigger.fromUid, work.threadId ?? source, source,
61
+ JSON.stringify({ text: trigger.payload.body, authorName: String(humans[0]['name'] ?? 'Learner'), missionId: mission.id })]);
62
+ }
63
+ return { mission, inserted: stored.inserted };
64
+ });
65
+ api.inc(result.inserted ? 'learning.mission.created' : 'learning.mission.deduplicated', result.inserted ? { mode: 'agent' } : undefined);
66
+ const mission = result.mission;
67
+ await services.wukongClient().sendMessage(work.sessionId, channelType, work.agentId, {
68
+ version: 1, kind: 'learning_mission', clientMsgNo: `learning-mission-${mission.id}`, body: mission.goal, refs: { agentId: work.agentId },
69
+ data: { missionId: mission.id, projectId: room.projectId, ...(room.courseId ? { courseId: room.courseId } : {}),
70
+ goal: mission.goal, successCriteria: mission.successCriteria, kind: mission.kind, coordinatorAgentId: mission.coordinatorAgentId,
71
+ status: mission.status, suppressAgentWake: true },
72
+ });
73
+ return mission;
74
+ }
75
+ export async function assertMissionCoordinatorWork(database, services, work) {
76
+ if (!services.learning || !work.principalId || typeof work.meta?.['missionId'] !== 'string')
77
+ throw new Error('Mission coordinator identity is missing');
78
+ await services.permissionService.assertCan({ actorUserId: work.principalId, companyId: work.tenantId,
79
+ action: 'learning:submit', resource: { type: 'conversation', id: work.sessionId } });
80
+ const room = await services.learning.findLearningRoomState(database, { companyId: work.tenantId, channelId: work.sessionId });
81
+ const mission = room && await services.learning.findLearningMission(database, work.tenantId, room.projectId, work.meta['missionId']);
82
+ if (!mission || mission.learnerId !== work.principalId || mission.conversationId !== work.sessionId
83
+ || mission.coordinatorAgentId !== work.agentId || mission.triggerClientMsgNo !== work.triggerRef)
84
+ throw new Error('Mission coordinator assignment or scope changed');
85
+ if (!['PLANNING', 'ACTIVE', 'COMPLETED'].includes(mission.status))
86
+ throw new Error('Mission is no longer runnable');
87
+ const eligible = await database.query(`SELECT 1 FROM participants agent JOIN conversations conversation
88
+ ON conversation.company_id=agent.company_id AND conversation.id=$3 AND conversation.project_id=$4
89
+ WHERE agent.company_id=$1 AND agent.id=$2 AND agent.kind='agent' AND agent.departed_at IS NULL
90
+ AND agent.capabilities @> '["canvas","learning"]'::jsonb AND conversation.members ? agent.id`, [work.tenantId, work.agentId, work.sessionId, mission.projectId]);
91
+ if (eligible.rows.length !== 1)
92
+ throw new Error('Mission coordinator is no longer eligible');
93
+ return mission.id;
94
+ }
95
+ //# sourceMappingURL=learning-missions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learning-missions.js","sourceRoot":"","sources":["../../../../src/integrations/lingxiloop/learning-missions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { HostAction, WorkItem } from '../../protocol/types.js';
2
+ import type { LingxiLoopServices } from './service-contracts.js';
3
+ export declare const LEARNING_METHODS: {
4
+ readonly list_attempts: readonly ["activityId", "missionStepId"];
5
+ readonly get_attempt: readonly ["attemptId"];
6
+ readonly propose_evaluation: readonly ["attemptId", "demonstratedLevel", "confidence", "rubricResults", "feedback", "sourceEvidenceId", "verifierEvidenceId"];
7
+ readonly record_attempt: readonly ["activityId", "missionStepId", "evidenceClientMsgNos", "documentIds", "canvasFrameIds", "assistance"];
8
+ readonly draft_knowledge_units: readonly ["knowledgeUnits"];
9
+ readonly draft_activity: readonly ["title", "instructions", "kind", "evaluationMode", "targetLevel", "rubric", "knowledgeUnitIds", "dueAt"];
10
+ readonly start_mission: readonly ["goal", "successCriteria", "missionKind", "sourceClientMsgNo", "explicit"];
11
+ readonly update_step: readonly ["missionId", "stepId", "status", "outcome", "sourceEvidenceId", "attemptId"];
12
+ readonly add_steps: readonly ["missionId", "steps"];
13
+ readonly finish_planning: readonly ["missionId"];
14
+ readonly complete_mission: readonly ["missionId"];
15
+ readonly current: readonly [];
16
+ readonly get_learner_state: readonly [];
17
+ readonly list_knowledge_units: readonly [];
18
+ readonly list_due: readonly [];
19
+ readonly get_mission: readonly ["missionId"];
20
+ readonly get_activity: readonly ["activityId"];
21
+ };
22
+ export declare function executeLearning(work: Omit<WorkItem, 'leaseToken'>, action: HostAction, services: Pick<LingxiLoopServices, 'learning' | 'permissionService'>): Promise<unknown>;