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,26 @@
1
+ /**
2
+ * Protocol-wide constants.
3
+ *
4
+ * Version numbers gate compatibility between independently deployed pieces
5
+ * (control plane, workers, kernels). Bump a version only for a breaking wire
6
+ * change; additive optional fields do not require a bump.
7
+ */
8
+ /** Control-plane HTTP API and worker claim protocol. */
9
+ export const AGENT_OS_PROTOCOL_VERSION = 2;
10
+ /** Kernel stdio (NDJSON) protocol between the manager and `kernel/runner.py`. */
11
+ export const KERNEL_PROTOCOL_VERSION = 2;
12
+ /**
13
+ * Each lease attempt of a run owns a disjoint event-sequence range:
14
+ * `((fence - 1) * RUN_SEQUENCE_SPAN, fence * RUN_SEQUENCE_SPAN]`.
15
+ *
16
+ * A retried attempt therefore never collides with — and is never deduplicated
17
+ * against — events persisted by an earlier attempt of the same run.
18
+ */
19
+ export const RUN_SEQUENCE_SPAN = 100_000;
20
+ /** Upper bound applied to any single tool/host payload surfaced to the model. */
21
+ export const MAX_TOOL_OUTPUT_CHARS = 8_000;
22
+ /** Name of the single tool exposed to the model. */
23
+ export const IPYTHON_TOOL_NAME = 'ipython';
24
+ /** Name of the in-kernel SDK module the model calls (`host.<capability>.<method>`). */
25
+ export const KERNEL_SDK_MODULE = 'host';
26
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/protocol/constants.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,wDAAwD;AACxD,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAU,CAAA;AAEnD,iFAAiF;AACjF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAU,CAAA;AAEjD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAgB,CAAA;AAEjD,iFAAiF;AACjF,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAc,CAAA;AAEnD,oDAAoD;AACpD,MAAM,CAAC,MAAM,iBAAiB,GAAG,SAAkB,CAAA;AAEnD,uFAAuF;AACvF,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAe,CAAA"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * NDJSON stdio protocol between the kernel manager and `kernel/runner.py`.
3
+ *
4
+ * Framing: one JSON object per line, ASCII-safe (non-ASCII escaped) so the
5
+ * transport is locale-independent (`python -I` ignores PYTHONIOENCODING).
6
+ *
7
+ * Concurrency model: the manager serializes executions per kernel; while an
8
+ * execution is in flight the only messages the manager may write are the
9
+ * `host_result` replies to that execution's `host_call`s. The runner blocks
10
+ * synchronously inside a host call, which is what makes the bridge appear as
11
+ * ordinary synchronous Python to model-authored code.
12
+ */
13
+ import type { CapabilityGrant, HostDirective, KernelArtifact } from './types.js';
14
+ export interface KernelExecuteRequest {
15
+ type: 'execute';
16
+ id: string;
17
+ code: string;
18
+ context: {
19
+ runId: string;
20
+ cellId: string;
21
+ capabilities: CapabilityGrant[];
22
+ };
23
+ }
24
+ export interface KernelHostResultMessage {
25
+ type: 'host_result';
26
+ requestId: string;
27
+ ok: boolean;
28
+ value?: unknown;
29
+ error?: string;
30
+ approval?: {
31
+ id: string;
32
+ status: 'PENDING';
33
+ };
34
+ directive?: HostDirective;
35
+ }
36
+ export interface KernelShutdownRequest {
37
+ type: 'shutdown';
38
+ }
39
+ export type ManagerToKernel = KernelExecuteRequest | KernelHostResultMessage | KernelShutdownRequest;
40
+ export interface KernelReadyMessage {
41
+ type: 'ready';
42
+ protocol: number;
43
+ python: string;
44
+ engine: 'ipython' | 'basic';
45
+ home: string;
46
+ }
47
+ export interface KernelHostCallMessage {
48
+ type: 'host_call';
49
+ /** Execution id this call belongs to — required for correlation. */
50
+ id: string;
51
+ requestId: string;
52
+ callIndex: number;
53
+ action: string;
54
+ args: Record<string, unknown>;
55
+ }
56
+ export interface KernelExecutionResultMessage {
57
+ type: 'execution_result';
58
+ id: string;
59
+ ok: boolean;
60
+ stdout: string;
61
+ stderr: string;
62
+ result: unknown;
63
+ error: string | null;
64
+ approvalId: string | null;
65
+ truncated: boolean;
66
+ durationMs: number;
67
+ artifacts: KernelArtifact[];
68
+ directives: HostDirective[];
69
+ }
70
+ export interface KernelProtocolErrorMessage {
71
+ type: 'protocol_error';
72
+ error: string;
73
+ }
74
+ export type KernelToManager = KernelReadyMessage | KernelHostCallMessage | KernelExecutionResultMessage | KernelProtocolErrorMessage;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=kernel-wire.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kernel-wire.js","sourceRoot":"","sources":["../../../src/protocol/kernel-wire.ts"],"names":[],"mappings":""}
@@ -0,0 +1,16 @@
1
+ export type Verification = 'passed' | 'not_run' | 'inconclusive';
2
+ export type GoalOutcome = {
3
+ requestVersion: number;
4
+ verification: Verification;
5
+ gaps?: string[];
6
+ question?: string;
7
+ } & ({
8
+ status: 'satisfied' | 'partial' | 'awaiting_input' | 'blocked';
9
+ } | {
10
+ status: 'awaiting_approval';
11
+ approvalId: string;
12
+ } | {
13
+ status: 'delegated';
14
+ taskRef: string;
15
+ });
16
+ export declare function isGoalOutcome(value: unknown): value is GoalOutcome;
@@ -0,0 +1,14 @@
1
+ export function isGoalOutcome(value) {
2
+ if (!value || typeof value !== 'object')
3
+ return false;
4
+ const item = value;
5
+ return Number.isSafeInteger(item['requestVersion']) && Number(item['requestVersion']) > 0
6
+ && typeof item['verification'] === 'string' && ['passed', 'not_run', 'inconclusive'].includes(item['verification'])
7
+ && typeof item['status'] === 'string' && ['satisfied', 'partial', 'awaiting_input', 'awaiting_approval', 'delegated', 'blocked'].includes(item['status'])
8
+ && (item['gaps'] === undefined || (Array.isArray(item['gaps']) && item['gaps'].every((gap) => typeof gap === 'string')))
9
+ && (item['question'] === undefined || (item['status'] === 'awaiting_input' && typeof item['question'] === 'string' && item['question'].trim().length > 0 && item['question'].length <= 4_000))
10
+ && (item['status'] !== 'satisfied' || item['gaps'] === undefined || item['gaps'].length === 0)
11
+ && (item['status'] !== 'awaiting_approval' || (typeof item['approvalId'] === 'string' && item['approvalId'].trim().length > 0))
12
+ && (item['status'] !== 'delegated' || (typeof item['taskRef'] === 'string' && item['taskRef'].trim().length > 0));
13
+ }
14
+ //# sourceMappingURL=outcome.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outcome.js","sourceRoot":"","sources":["../../../src/protocol/outcome.ts"],"names":[],"mappings":"AAaA,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IACrD,MAAM,IAAI,GAAG,KAAgC,CAAA;IAC7C,OAAO,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC;WACpF,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,QAAQ,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;WAChH,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,QAAQ,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;WACtJ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC;WACrH,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,gBAAgB,IAAI,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC;WAC3L,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,WAAW,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,SAAS,IAAK,IAAI,CAAC,MAAM,CAAe,CAAC,MAAM,KAAK,CAAC,CAAC;WAC1G,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,mBAAmB,IAAI,CAAC,OAAO,IAAI,CAAC,YAAY,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;WAC5H,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,WAAW,IAAI,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAA;AACrH,CAAC"}
@@ -0,0 +1,266 @@
1
+ /**
2
+ * Core protocol types shared by the control plane, workers, kernels, and
3
+ * extensions. This module is intentionally logic-free: every layer depends on
4
+ * it and it depends on nothing.
5
+ */
6
+ /**
7
+ * Why a work item exists. `turn` is the ordinary conversational turn handled
8
+ * by the runtime's agent loop; every other kind is routed to a registered
9
+ * {@link import('../runtime/runtime.js').WorkProcessor}.
10
+ */
11
+ export type WorkKind = 'turn' | 'resume' | (string & {});
12
+ /** Scheduling lane. Higher lanes are claimed before lower ones. */
13
+ export type WorkLane = 'interactive' | 'approval' | 'collaboration' | 'background';
14
+ export declare const WORK_LANE_PRIORITY: Readonly<Record<WorkLane, number>>;
15
+ export type WorkStatus = 'queued' | 'leased' | 'completed' | 'failed' | 'cancelled';
16
+ /**
17
+ * A durable unit of agent work, claimed under a fenced lease.
18
+ *
19
+ * Invariants:
20
+ * - `fence` increases by exactly one on every lease acquisition and every
21
+ * yield, and never decreases. Every mutating control-plane call carries
22
+ * `(id, fence, leaseToken)` and is rejected unless all three match the
23
+ * current lease.
24
+ * - `id` doubles as the run id: a retried attempt reuses every externally
25
+ * visible identity, and attempt separation happens through the fence-scoped
26
+ * event-sequence ranges (see `RUN_SEQUENCE_SPAN`).
27
+ */
28
+ export interface WorkItem {
29
+ id: string;
30
+ fence: number;
31
+ /**
32
+ * Increments when the session is re-routed to a different worker, so a
33
+ * kernel filesystem home written by a lost worker is never reused.
34
+ */
35
+ homeEpoch: number;
36
+ tenantId: string;
37
+ agentId: string;
38
+ sessionId: string;
39
+ /** Optional sub-thread inside the session. */
40
+ threadId?: string;
41
+ kind: WorkKind;
42
+ lane: WorkLane;
43
+ /** Opaque reference to whatever triggered this work (message id, cron id…). */
44
+ triggerRef: string;
45
+ /** Human principal whose authorization the work runs under, if any. */
46
+ principalId?: string;
47
+ createdAt?: string;
48
+ availableAt?: string;
49
+ attempts?: number;
50
+ preemptions?: number;
51
+ /** Bearer proof of the current lease. Never persisted in clear text. */
52
+ leaseToken: string;
53
+ /** Deployment-defined extra routing/context payload (opaque to the core). */
54
+ meta?: Record<string, unknown>;
55
+ }
56
+ export interface WorkCompletion {
57
+ goalOutcome?: import('./outcome.js').GoalOutcome;
58
+ status: 'completed' | 'failed' | 'cancelled';
59
+ resultText?: string;
60
+ error?: string;
61
+ }
62
+ /**
63
+ * A capability grants access to one host-bridge namespace, optionally
64
+ * restricted to specific methods. Grants are enforced twice: advisorily
65
+ * inside the kernel (the model cannot even *name* an ungranted method) and
66
+ * authoritatively in the control plane before any action executes.
67
+ */
68
+ export interface CapabilityGrant {
69
+ name: string;
70
+ /** When present, only these methods are callable. */
71
+ methods?: readonly string[];
72
+ }
73
+ /**
74
+ * One product side effect requested by kernel code via
75
+ * `host.<namespace>.<method>(...)`.
76
+ *
77
+ * `idempotencyKey` is the JSON tuple `[runId, cellId, callIndex]` — deterministic
78
+ * across kernel restarts replaying the same cell — so the control-plane
79
+ * action ledger can reject changed intents and avoid blindly replaying effects.
80
+ */
81
+ export interface HostAction {
82
+ runId: string;
83
+ cellId: string;
84
+ callIndex: number;
85
+ /** `<namespace>.<method>` */
86
+ action: string;
87
+ args: Record<string, unknown>;
88
+ idempotencyKey: string;
89
+ }
90
+ export declare function actionKeyOf(action: Pick<HostAction, 'runId' | 'cellId' | 'callIndex'>): string;
91
+ export interface HostActionResult {
92
+ ok: boolean;
93
+ executionState?: 'unknown';
94
+ value?: unknown;
95
+ error?: string;
96
+ /** Present when the action suspended into a human approval. */
97
+ approval?: {
98
+ id: string;
99
+ status: 'PENDING';
100
+ };
101
+ /** Optional host instruction back to the runtime. */
102
+ directive?: HostDirective;
103
+ }
104
+ /**
105
+ * A host directive lets an action tell the runtime that the turn is finished
106
+ * out-of-band (e.g. work was handed to another surface, or the host asked the
107
+ * user a blocking question). The runtime completes the run successfully
108
+ * without a final assistant message.
109
+ */
110
+ export interface HostDirective {
111
+ type: 'defer' | 'task_contract';
112
+ reason?: string;
113
+ data?: Record<string, unknown>;
114
+ }
115
+ export interface ApprovalResolution {
116
+ approvalId: string;
117
+ approved: boolean;
118
+ result?: unknown;
119
+ error?: string;
120
+ }
121
+ export interface KernelArtifact {
122
+ path: string;
123
+ size: number;
124
+ mime: string;
125
+ sha256: string;
126
+ }
127
+ export interface KernelExecution {
128
+ executionId: string;
129
+ stdout: string;
130
+ stderr: string;
131
+ result: unknown;
132
+ durationMs: number;
133
+ truncated: boolean;
134
+ artifacts: KernelArtifact[];
135
+ directives: HostDirective[];
136
+ }
137
+ export type RunStage = 'started' | 'delta' | 'completed' | 'failed' | 'cancelled';
138
+ /**
139
+ * A single durable event of a run attempt. `seq` must fall inside the
140
+ * attempt's fence-scoped range; the control plane rejects events outside it
141
+ * and deduplicates on `(runId, seq)`.
142
+ */
143
+ export interface RunEvent {
144
+ runId: string;
145
+ seq: number;
146
+ kind: string;
147
+ stage: RunStage;
148
+ /** `user` events may be surfaced to end users; `internal` never are. */
149
+ visibility: 'user' | 'internal';
150
+ data: Record<string, unknown>;
151
+ }
152
+ export type ModelItem = {
153
+ role: 'user' | 'assistant' | 'system';
154
+ content: string;
155
+ } | {
156
+ type: 'function_call';
157
+ callId: string;
158
+ name: string;
159
+ arguments: string;
160
+ } | {
161
+ type: 'function_call_output';
162
+ callId: string;
163
+ output: string;
164
+ };
165
+ /**
166
+ * Durable conversational state of one agent session, saved with optimistic
167
+ * concurrency (`revision`).
168
+ */
169
+ export interface SessionRecord {
170
+ request?: import('../context/request.js').RequestSnapshot;
171
+ key: string;
172
+ tenantId: string;
173
+ agentId: string;
174
+ sessionId: string;
175
+ threadId?: string;
176
+ summary?: string;
177
+ history: ModelItem[];
178
+ /** Work ids whose turn input is already folded into `history`. */
179
+ appliedWorkIds: string[];
180
+ revision: number;
181
+ compactionEpoch: number;
182
+ /** Frozen system-prompt context; rebuilt when its source versions change. */
183
+ promptContext?: PromptContext;
184
+ }
185
+ /** Composite key shared by sessions, kernel affinity, and lease exclusivity. */
186
+ export declare function sessionKeyOf(work: Pick<WorkItem, 'tenantId' | 'agentId' | 'sessionId' | 'threadId'>): string;
187
+ /**
188
+ * The cache-stable prefix of the model conversation. Frozen into the session
189
+ * and only rebuilt when a source version changes, so provider prompt caches
190
+ * stay warm across turns.
191
+ */
192
+ export interface PromptContext {
193
+ version: 2;
194
+ epoch: number;
195
+ assembledAt: string;
196
+ systemInstructions: string;
197
+ persona: {
198
+ name: string;
199
+ role: string;
200
+ instructions: string;
201
+ };
202
+ capabilities: string[];
203
+ /** Versions of everything folded into `systemInstructions`. */
204
+ sourceVersions: Record<string, string>;
205
+ }
206
+ export interface ContextMessage {
207
+ ref: string;
208
+ authorId: string;
209
+ authorName: string;
210
+ authorKind: 'human' | 'agent' | 'system';
211
+ body: string;
212
+ createdAt: string;
213
+ replyToRef?: string;
214
+ }
215
+ /**
216
+ * Everything the runtime needs to run one attempt. Split into a cache-stable
217
+ * candidate prompt context and per-turn dynamic context that is never frozen
218
+ * into the session.
219
+ */
220
+ export interface TurnContext {
221
+ memory?: import('../memory/store.js').MemorySnapshot;
222
+ /** Prior attempt records only; files must be rechecked before current delivery. */
223
+ priorArtifacts?: KernelArtifact[];
224
+ evidence?: import('../context/evidence.js').EvidenceItem[];
225
+ work: WorkItem;
226
+ persona: {
227
+ name: string;
228
+ role: string;
229
+ instructions: string;
230
+ };
231
+ capabilities: string[];
232
+ messages: ContextMessage[];
233
+ promptContextCandidate?: PromptContext;
234
+ pendingApproval?: ApprovalResolution;
235
+ /**
236
+ * Deployment-defined per-turn context (retrieval results, live product
237
+ * state…). Rendered by the active RuntimePolicy; opaque to the core.
238
+ */
239
+ dynamic?: Record<string, unknown>;
240
+ }
241
+ export interface SteerInput {
242
+ id: string;
243
+ text: string;
244
+ createdAt: string;
245
+ attachments?: import('../context/attachments.js').RequestAttachment[];
246
+ }
247
+ export interface HeartbeatResult {
248
+ ok: boolean;
249
+ cancelRequested?: boolean;
250
+ preemptRequested?: boolean;
251
+ steer?: SteerInput[];
252
+ }
253
+ /**
254
+ * The final user-visible assistant message of a turn. The control plane
255
+ * verifies `body` byte-for-byte against the durably streamed deltas of the
256
+ * same attempt before delivering it.
257
+ */
258
+ export interface AssistantMessage {
259
+ envelope: import('../outcome/envelope.js').ResponseEnvelope;
260
+ version: 2;
261
+ runId: string;
262
+ agentId: string;
263
+ sessionId: string;
264
+ threadId?: string;
265
+ body: string;
266
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Core protocol types shared by the control plane, workers, kernels, and
3
+ * extensions. This module is intentionally logic-free: every layer depends on
4
+ * it and it depends on nothing.
5
+ */
6
+ export const WORK_LANE_PRIORITY = Object.freeze({
7
+ interactive: 4,
8
+ approval: 3,
9
+ collaboration: 2,
10
+ background: 1,
11
+ });
12
+ export function actionKeyOf(action) {
13
+ return JSON.stringify([action.runId, action.cellId, action.callIndex]);
14
+ }
15
+ /** Composite key shared by sessions, kernel affinity, and lease exclusivity. */
16
+ export function sessionKeyOf(work) {
17
+ return JSON.stringify([work.tenantId, work.agentId, work.sessionId, work.threadId ?? null]);
18
+ }
19
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/protocol/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAgBH,MAAM,CAAC,MAAM,kBAAkB,GAAuC,MAAM,CAAC,MAAM,CAAC;IAClF,WAAW,EAAE,CAAC;IACd,QAAQ,EAAE,CAAC;IACX,aAAa,EAAE,CAAC;IAChB,UAAU,EAAE,CAAC;CACd,CAAC,CAAA;AA0FF,MAAM,UAAU,WAAW,CAAC,MAA0D;IACpF,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAA;AACxE,CAAC;AAyGD,gFAAgF;AAChF,MAAM,UAAU,YAAY,CAAC,IAAuE;IAClG,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAA;AAC7F,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function isPublicAddress(address: string): boolean;
2
+ export declare function researchUrl(raw: string): URL;
@@ -0,0 +1,32 @@
1
+ import { BlockList, isIP } from 'node:net';
2
+ const blocked = new BlockList();
3
+ for (const [address, prefix] of [
4
+ ['0.0.0.0', 8], ['10.0.0.0', 8], ['100.64.0.0', 10], ['127.0.0.0', 8],
5
+ ['169.254.0.0', 16], ['172.16.0.0', 12], ['192.0.0.0', 24], ['192.0.2.0', 24],
6
+ ['192.168.0.0', 16], ['198.18.0.0', 15], ['198.51.100.0', 24], ['203.0.113.0', 24],
7
+ ['224.0.0.0', 4], ['240.0.0.0', 4],
8
+ ])
9
+ blocked.addSubnet(address, prefix, 'ipv4');
10
+ const globalV6 = new BlockList();
11
+ globalV6.addSubnet('2000::', 3, 'ipv6');
12
+ for (const [address, prefix] of [['2001::', 23], ['2001:db8::', 32], ['2002::', 16], ['3fff::', 20]]) {
13
+ blocked.addSubnet(address, prefix, 'ipv6');
14
+ }
15
+ export function isPublicAddress(address) {
16
+ const family = isIP(address);
17
+ if (family === 4)
18
+ return !blocked.check(address, 'ipv4');
19
+ return family === 6 && globalV6.check(address, 'ipv6') && !blocked.check(address, 'ipv6');
20
+ }
21
+ export function researchUrl(raw) {
22
+ if (raw.length > 2048)
23
+ throw new Error('research URL is too long');
24
+ const url = new URL(raw);
25
+ if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password)
26
+ throw new Error('research URL requires HTTP(S) without credentials');
27
+ const host = url.hostname.replace(/^\[|\]$/g, '').toLowerCase();
28
+ if (!host || host === 'localhost' || host.endsWith('.localhost') || host.endsWith('.local') || (isIP(host) && !isPublicAddress(host)))
29
+ throw new Error('research URL host is blocked');
30
+ return url;
31
+ }
32
+ //# sourceMappingURL=address.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"address.js","sourceRoot":"","sources":["../../../src/research/address.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AAE1C,MAAM,OAAO,GAAG,IAAI,SAAS,EAAE,CAAA;AAC/B,KAAK,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI;IAC9B,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IACrE,CAAC,aAAa,EAAE,EAAE,CAAC,EAAE,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;IAC7E,CAAC,aAAa,EAAE,EAAE,CAAC,EAAE,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,CAAC;IAClF,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;CAC1B;IAAE,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AACtD,MAAM,QAAQ,GAAG,IAAI,SAAS,EAAE,CAAA;AAChC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,EAAE,MAAM,CAAC,CAAA;AACvC,KAAK,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAU,EAAE,CAAC;IAC9G,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAC5C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,CAAA;IAC5B,IAAI,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IACxD,OAAO,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;AAC3F,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,IAAI,GAAG,CAAC,MAAM,GAAG,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;IAClE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;IACxB,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAA;IACrJ,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAA;IAC/D,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAA;IACtL,OAAO,GAAG,CAAA;AACZ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type RequestOptions } from 'node:https';
2
+ export declare function pinnedRequestOptions(url: URL, address: string): RequestOptions;
3
+ export declare function fetchResearch(raw: string): Promise<{
4
+ url: string;
5
+ contentType: string;
6
+ body: Buffer;
7
+ }>;
@@ -0,0 +1,83 @@
1
+ import { lookup } from 'node:dns/promises';
2
+ import { request as httpRequest } from 'node:http';
3
+ import { request as httpsRequest } from 'node:https';
4
+ import { isIP } from 'node:net';
5
+ import { isPublicAddress, researchUrl } from './address.js';
6
+ const MAX_BYTES = 2 * 1024 * 1024;
7
+ export function pinnedRequestOptions(url, address) {
8
+ if (!isPublicAddress(address))
9
+ throw new Error('research address is blocked');
10
+ const host = url.hostname.replace(/^\[|\]$/g, '');
11
+ return { hostname: address, agent: false,
12
+ ...(!isIP(host) ? { servername: host } : {}),
13
+ headers: { host: url.host, accept: 'text/html,application/json,text/plain', 'accept-encoding': 'identity', 'user-agent': 'LingxiOS-Research/1.0' },
14
+ };
15
+ }
16
+ export async function fetchResearch(raw) {
17
+ const controller = new AbortController();
18
+ let timeout;
19
+ const expired = new Promise((_resolve, reject) => {
20
+ timeout = setTimeout(() => { controller.abort(); reject(new Error('research request timed out')); }, 15_000);
21
+ });
22
+ try {
23
+ return await Promise.race([expired, (async () => {
24
+ let url = researchUrl(raw);
25
+ for (let redirects = 0; redirects <= 5; redirects++) {
26
+ const host = url.hostname.replace(/^\[|\]$/g, '');
27
+ const addresses = isIP(host) ? [{ address: host }] : await lookup(host, { all: true, verbatim: true });
28
+ if (!addresses.length || addresses.some(item => !isPublicAddress(item.address)))
29
+ throw new Error('research DNS resolved to a blocked address');
30
+ controller.signal.throwIfAborted();
31
+ const result = await new Promise((resolve, reject) => {
32
+ const request = (url.protocol === 'https:' ? httpsRequest : httpRequest)(url, {
33
+ ...pinnedRequestOptions(url, addresses[0].address), signal: controller.signal,
34
+ }, response => {
35
+ const status = response.statusCode ?? 0;
36
+ if (status >= 300 && status < 400) {
37
+ const location = response.headers.location;
38
+ response.destroy();
39
+ if (!location)
40
+ reject(new Error('research redirect has no location'));
41
+ else
42
+ resolve({ redirect: location });
43
+ return;
44
+ }
45
+ if (status < 200 || status >= 300 || Number(response.headers['content-length'] ?? 0) > MAX_BYTES) {
46
+ response.destroy();
47
+ reject(new Error(`research response rejected (HTTP ${status}, size limit ${MAX_BYTES})`));
48
+ return;
49
+ }
50
+ if (response.headers['content-encoding'] && response.headers['content-encoding'] !== 'identity') {
51
+ response.destroy();
52
+ reject(new Error('research source returned unsupported content encoding'));
53
+ return;
54
+ }
55
+ const chunks = [];
56
+ let size = 0;
57
+ response.on('data', (chunk) => {
58
+ size += chunk.length;
59
+ if (size > MAX_BYTES)
60
+ response.destroy(new Error('research source exceeds 2 MiB'));
61
+ else
62
+ chunks.push(chunk);
63
+ });
64
+ response.on('error', reject);
65
+ response.on('end', () => resolve({ url: url.href, contentType: String(response.headers['content-type'] ?? 'application/octet-stream').split(';')[0].toLowerCase(), body: Buffer.concat(chunks) }));
66
+ });
67
+ request.on('error', reject);
68
+ request.end();
69
+ });
70
+ if (!('redirect' in result))
71
+ return result;
72
+ if (redirects === 5)
73
+ throw new Error('research source redirected too many times');
74
+ url = researchUrl(new URL(result.redirect, url).href);
75
+ }
76
+ throw new Error('research redirect limit exceeded');
77
+ })()]);
78
+ }
79
+ finally {
80
+ clearTimeout(timeout);
81
+ }
82
+ }
83
+ //# sourceMappingURL=fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../../src/research/fetch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ export interface ResearchSearchResult {
2
+ title: string;
3
+ url: string;
4
+ doi?: string;
5
+ publicationYear?: number;
6
+ authors: string[];
7
+ abstract?: string;
8
+ citedByCount?: number;
9
+ source: 'OpenAlex';
10
+ }
11
+ export declare function searchResearch(query: string, limit?: number): Promise<{
12
+ provider: 'OpenAlex';
13
+ query: string;
14
+ results: ResearchSearchResult[];
15
+ }>;
16
+ export declare function parseOpenAlex(value: unknown, count: number): ResearchSearchResult[];
17
+ export declare function decodeHtml(value: string): string;
18
+ export declare function readResearch(rawUrl: string): Promise<{
19
+ url: string;
20
+ finalUrl: string;
21
+ contentType: string;
22
+ text: string;
23
+ bytes: number;
24
+ sha256: string;
25
+ truncated: boolean;
26
+ }>;