@inhuman.tools/turn 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (346) hide show
  1. package/LICENSE.md +7 -0
  2. package/dist/agent-calls/acceptance.d.ts +12 -0
  3. package/dist/agent-calls/acceptance.d.ts.map +1 -0
  4. package/dist/agent-calls/acceptance.js +64 -0
  5. package/dist/agent-calls/acceptance.js.map +1 -0
  6. package/dist/agent-calls/callbacks.d.ts +14 -0
  7. package/dist/agent-calls/callbacks.d.ts.map +1 -0
  8. package/dist/agent-calls/callbacks.js +59 -0
  9. package/dist/agent-calls/callbacks.js.map +1 -0
  10. package/dist/agent-calls/delivery.d.ts +7 -0
  11. package/dist/agent-calls/delivery.d.ts.map +1 -0
  12. package/dist/agent-calls/delivery.js +16 -0
  13. package/dist/agent-calls/delivery.js.map +1 -0
  14. package/dist/agent-calls/index.d.ts +7 -0
  15. package/dist/agent-calls/index.d.ts.map +1 -0
  16. package/dist/agent-calls/index.js +6 -0
  17. package/dist/agent-calls/index.js.map +1 -0
  18. package/dist/agent-calls/operator.d.ts +21 -0
  19. package/dist/agent-calls/operator.d.ts.map +1 -0
  20. package/dist/agent-calls/operator.js +78 -0
  21. package/dist/agent-calls/operator.js.map +1 -0
  22. package/dist/agent-calls/runtime.d.ts +99 -0
  23. package/dist/agent-calls/runtime.d.ts.map +1 -0
  24. package/dist/agent-calls/runtime.js +245 -0
  25. package/dist/agent-calls/runtime.js.map +1 -0
  26. package/dist/agent-calls/types.d.ts +31 -0
  27. package/dist/agent-calls/types.d.ts.map +1 -0
  28. package/dist/agent-calls/types.js +2 -0
  29. package/dist/agent-calls/types.js.map +1 -0
  30. package/dist/context/compact-floors.d.ts +43 -0
  31. package/dist/context/compact-floors.d.ts.map +1 -0
  32. package/dist/context/compact-floors.js +52 -0
  33. package/dist/context/compact-floors.js.map +1 -0
  34. package/dist/context/compact.d.ts +42 -0
  35. package/dist/context/compact.d.ts.map +1 -0
  36. package/dist/context/compact.js +155 -0
  37. package/dist/context/compact.js.map +1 -0
  38. package/dist/context/delivery.d.ts +13 -0
  39. package/dist/context/delivery.d.ts.map +1 -0
  40. package/dist/context/delivery.js +6 -0
  41. package/dist/context/delivery.js.map +1 -0
  42. package/dist/context/history.d.ts +66 -0
  43. package/dist/context/history.d.ts.map +1 -0
  44. package/dist/context/history.js +573 -0
  45. package/dist/context/history.js.map +1 -0
  46. package/dist/context/index.d.ts +10 -0
  47. package/dist/context/index.d.ts.map +1 -0
  48. package/dist/context/index.js +10 -0
  49. package/dist/context/index.js.map +1 -0
  50. package/dist/context/observations.d.ts +7 -0
  51. package/dist/context/observations.d.ts.map +1 -0
  52. package/dist/context/observations.js +11 -0
  53. package/dist/context/observations.js.map +1 -0
  54. package/dist/context/retention/defaults.d.ts +10 -0
  55. package/dist/context/retention/defaults.d.ts.map +1 -0
  56. package/dist/context/retention/defaults.js +47 -0
  57. package/dist/context/retention/defaults.js.map +1 -0
  58. package/dist/context/retention/index.d.ts +14 -0
  59. package/dist/context/retention/index.d.ts.map +1 -0
  60. package/dist/context/retention/index.js +21 -0
  61. package/dist/context/retention/index.js.map +1 -0
  62. package/dist/context/retention/narrow.d.ts +22 -0
  63. package/dist/context/retention/narrow.d.ts.map +1 -0
  64. package/dist/context/retention/narrow.js +140 -0
  65. package/dist/context/retention/narrow.js.map +1 -0
  66. package/dist/context/retention/render.d.ts +37 -0
  67. package/dist/context/retention/render.d.ts.map +1 -0
  68. package/dist/context/retention/render.js +149 -0
  69. package/dist/context/retention/render.js.map +1 -0
  70. package/dist/context/retention/resolve.d.ts +51 -0
  71. package/dist/context/retention/resolve.d.ts.map +1 -0
  72. package/dist/context/retention/resolve.js +254 -0
  73. package/dist/context/retention/resolve.js.map +1 -0
  74. package/dist/context/retention/schema.d.ts +345 -0
  75. package/dist/context/retention/schema.d.ts.map +1 -0
  76. package/dist/context/retention/schema.js +149 -0
  77. package/dist/context/retention/schema.js.map +1 -0
  78. package/dist/context/retention/stamp.d.ts +25 -0
  79. package/dist/context/retention/stamp.d.ts.map +1 -0
  80. package/dist/context/retention/stamp.js +103 -0
  81. package/dist/context/retention/stamp.js.map +1 -0
  82. package/dist/context/retention/step.d.ts +33 -0
  83. package/dist/context/retention/step.d.ts.map +1 -0
  84. package/dist/context/retention/step.js +74 -0
  85. package/dist/context/retention/step.js.map +1 -0
  86. package/dist/context/retention/view.d.ts +57 -0
  87. package/dist/context/retention/view.d.ts.map +1 -0
  88. package/dist/context/retention/view.js +121 -0
  89. package/dist/context/retention/view.js.map +1 -0
  90. package/dist/context/squeeze.d.ts +45 -0
  91. package/dist/context/squeeze.d.ts.map +1 -0
  92. package/dist/context/squeeze.js +182 -0
  93. package/dist/context/squeeze.js.map +1 -0
  94. package/dist/context/tools.d.ts +16 -0
  95. package/dist/context/tools.d.ts.map +1 -0
  96. package/dist/context/tools.js +73 -0
  97. package/dist/context/tools.js.map +1 -0
  98. package/dist/context/transcript.d.ts +151 -0
  99. package/dist/context/transcript.d.ts.map +1 -0
  100. package/dist/context/transcript.js +659 -0
  101. package/dist/context/transcript.js.map +1 -0
  102. package/dist/policy-processor/bypass.d.ts +95 -0
  103. package/dist/policy-processor/bypass.d.ts.map +1 -0
  104. package/dist/policy-processor/bypass.js +188 -0
  105. package/dist/policy-processor/bypass.js.map +1 -0
  106. package/dist/policy-processor/classifier.d.ts +47 -0
  107. package/dist/policy-processor/classifier.d.ts.map +1 -0
  108. package/dist/policy-processor/classifier.js +671 -0
  109. package/dist/policy-processor/classifier.js.map +1 -0
  110. package/dist/policy-processor/cluster.d.ts +7 -0
  111. package/dist/policy-processor/cluster.d.ts.map +1 -0
  112. package/dist/policy-processor/cluster.js +32 -0
  113. package/dist/policy-processor/cluster.js.map +1 -0
  114. package/dist/policy-processor/evidence.d.ts +26 -0
  115. package/dist/policy-processor/evidence.d.ts.map +1 -0
  116. package/dist/policy-processor/evidence.js +204 -0
  117. package/dist/policy-processor/evidence.js.map +1 -0
  118. package/dist/policy-processor/explain.d.ts +59 -0
  119. package/dist/policy-processor/explain.d.ts.map +1 -0
  120. package/dist/policy-processor/explain.js +224 -0
  121. package/dist/policy-processor/explain.js.map +1 -0
  122. package/dist/policy-processor/index.d.ts +6 -0
  123. package/dist/policy-processor/index.d.ts.map +1 -0
  124. package/dist/policy-processor/index.js +6 -0
  125. package/dist/policy-processor/index.js.map +1 -0
  126. package/dist/policy-processor/license.d.ts +23 -0
  127. package/dist/policy-processor/license.d.ts.map +1 -0
  128. package/dist/policy-processor/license.js +47 -0
  129. package/dist/policy-processor/license.js.map +1 -0
  130. package/dist/policy-processor/peel-cwd.d.ts +2 -0
  131. package/dist/policy-processor/peel-cwd.d.ts.map +1 -0
  132. package/dist/policy-processor/peel-cwd.js +2 -0
  133. package/dist/policy-processor/peel-cwd.js.map +1 -0
  134. package/dist/policy-processor/real-path.d.ts +7 -0
  135. package/dist/policy-processor/real-path.d.ts.map +1 -0
  136. package/dist/policy-processor/real-path.js +42 -0
  137. package/dist/policy-processor/real-path.js.map +1 -0
  138. package/dist/policy-processor/scope.d.ts +111 -0
  139. package/dist/policy-processor/scope.d.ts.map +1 -0
  140. package/dist/policy-processor/scope.js +629 -0
  141. package/dist/policy-processor/scope.js.map +1 -0
  142. package/dist/policy-processor/self-protect.d.ts +10 -0
  143. package/dist/policy-processor/self-protect.d.ts.map +1 -0
  144. package/dist/policy-processor/self-protect.js +48 -0
  145. package/dist/policy-processor/self-protect.js.map +1 -0
  146. package/dist/policy-processor/soft-deny.d.ts +75 -0
  147. package/dist/policy-processor/soft-deny.d.ts.map +1 -0
  148. package/dist/policy-processor/soft-deny.js +185 -0
  149. package/dist/policy-processor/soft-deny.js.map +1 -0
  150. package/dist/policy-processor/unattended-guard.d.ts +28 -0
  151. package/dist/policy-processor/unattended-guard.d.ts.map +1 -0
  152. package/dist/policy-processor/unattended-guard.js +145 -0
  153. package/dist/policy-processor/unattended-guard.js.map +1 -0
  154. package/dist/session/cancel.d.ts +14 -0
  155. package/dist/session/cancel.d.ts.map +1 -0
  156. package/dist/session/cancel.js +32 -0
  157. package/dist/session/cancel.js.map +1 -0
  158. package/dist/session/commands.d.ts +41 -0
  159. package/dist/session/commands.d.ts.map +1 -0
  160. package/dist/session/commands.js +241 -0
  161. package/dist/session/commands.js.map +1 -0
  162. package/dist/session/compact-actor.d.ts +23 -0
  163. package/dist/session/compact-actor.d.ts.map +1 -0
  164. package/dist/session/compact-actor.js +91 -0
  165. package/dist/session/compact-actor.js.map +1 -0
  166. package/dist/session/compact-env.d.ts +54 -0
  167. package/dist/session/compact-env.d.ts.map +1 -0
  168. package/dist/session/compact-env.js +345 -0
  169. package/dist/session/compact-env.js.map +1 -0
  170. package/dist/session/compact.d.ts +42 -0
  171. package/dist/session/compact.d.ts.map +1 -0
  172. package/dist/session/compact.js +68 -0
  173. package/dist/session/compact.js.map +1 -0
  174. package/dist/session/index.d.ts +9 -0
  175. package/dist/session/index.d.ts.map +1 -0
  176. package/dist/session/index.js +8 -0
  177. package/dist/session/index.js.map +1 -0
  178. package/dist/session/park.d.ts +16 -0
  179. package/dist/session/park.d.ts.map +1 -0
  180. package/dist/session/park.js +73 -0
  181. package/dist/session/park.js.map +1 -0
  182. package/dist/session/side-channel-reminder.d.ts +41 -0
  183. package/dist/session/side-channel-reminder.d.ts.map +1 -0
  184. package/dist/session/side-channel-reminder.js +132 -0
  185. package/dist/session/side-channel-reminder.js.map +1 -0
  186. package/dist/session/types.d.ts +44 -0
  187. package/dist/session/types.d.ts.map +1 -0
  188. package/dist/session/types.js +2 -0
  189. package/dist/session/types.js.map +1 -0
  190. package/dist/tool-catalog/catalog.d.ts +77 -0
  191. package/dist/tool-catalog/catalog.d.ts.map +1 -0
  192. package/dist/tool-catalog/catalog.js +380 -0
  193. package/dist/tool-catalog/catalog.js.map +1 -0
  194. package/dist/tool-catalog/index.d.ts +4 -0
  195. package/dist/tool-catalog/index.d.ts.map +1 -0
  196. package/dist/tool-catalog/index.js +3 -0
  197. package/dist/tool-catalog/index.js.map +1 -0
  198. package/dist/tool-catalog/recipes.d.ts +36 -0
  199. package/dist/tool-catalog/recipes.d.ts.map +1 -0
  200. package/dist/tool-catalog/recipes.js +121 -0
  201. package/dist/tool-catalog/recipes.js.map +1 -0
  202. package/dist/tool-catalog/types.d.ts +103 -0
  203. package/dist/tool-catalog/types.d.ts.map +1 -0
  204. package/dist/tool-catalog/types.js +5 -0
  205. package/dist/tool-catalog/types.js.map +1 -0
  206. package/dist/tool-runtime/approval/approved.d.ts +13 -0
  207. package/dist/tool-runtime/approval/approved.d.ts.map +1 -0
  208. package/dist/tool-runtime/approval/approved.js +20 -0
  209. package/dist/tool-runtime/approval/approved.js.map +1 -0
  210. package/dist/tool-runtime/approval/dist.d.ts +6 -0
  211. package/dist/tool-runtime/approval/dist.d.ts.map +1 -0
  212. package/dist/tool-runtime/approval/dist.js +28 -0
  213. package/dist/tool-runtime/approval/dist.js.map +1 -0
  214. package/dist/tool-runtime/approval/inbound.d.ts +7 -0
  215. package/dist/tool-runtime/approval/inbound.d.ts.map +1 -0
  216. package/dist/tool-runtime/approval/inbound.js +48 -0
  217. package/dist/tool-runtime/approval/inbound.js.map +1 -0
  218. package/dist/tool-runtime/approval/unattended.d.ts +8 -0
  219. package/dist/tool-runtime/approval/unattended.d.ts.map +1 -0
  220. package/dist/tool-runtime/approval/unattended.js +23 -0
  221. package/dist/tool-runtime/approval/unattended.js.map +1 -0
  222. package/dist/tool-runtime/blob-port.d.ts +46 -0
  223. package/dist/tool-runtime/blob-port.d.ts.map +1 -0
  224. package/dist/tool-runtime/blob-port.js +47 -0
  225. package/dist/tool-runtime/blob-port.js.map +1 -0
  226. package/dist/tool-runtime/extra-root.d.ts +3 -0
  227. package/dist/tool-runtime/extra-root.d.ts.map +1 -0
  228. package/dist/tool-runtime/extra-root.js +14 -0
  229. package/dist/tool-runtime/extra-root.js.map +1 -0
  230. package/dist/tool-runtime/handler.d.ts +29 -0
  231. package/dist/tool-runtime/handler.d.ts.map +1 -0
  232. package/dist/tool-runtime/handler.js +460 -0
  233. package/dist/tool-runtime/handler.js.map +1 -0
  234. package/dist/tool-runtime/index.d.ts +14 -0
  235. package/dist/tool-runtime/index.d.ts.map +1 -0
  236. package/dist/tool-runtime/index.js +14 -0
  237. package/dist/tool-runtime/index.js.map +1 -0
  238. package/dist/tool-runtime/peel.d.ts +19 -0
  239. package/dist/tool-runtime/peel.d.ts.map +1 -0
  240. package/dist/tool-runtime/peel.js +74 -0
  241. package/dist/tool-runtime/peel.js.map +1 -0
  242. package/dist/tool-runtime/plugin-context.d.ts +13 -0
  243. package/dist/tool-runtime/plugin-context.d.ts.map +1 -0
  244. package/dist/tool-runtime/plugin-context.js +55 -0
  245. package/dist/tool-runtime/plugin-context.js.map +1 -0
  246. package/dist/tool-runtime/recall.d.ts +18 -0
  247. package/dist/tool-runtime/recall.d.ts.map +1 -0
  248. package/dist/tool-runtime/recall.js +100 -0
  249. package/dist/tool-runtime/recall.js.map +1 -0
  250. package/dist/tool-runtime/run-system-tool.d.ts +13 -0
  251. package/dist/tool-runtime/run-system-tool.d.ts.map +1 -0
  252. package/dist/tool-runtime/run-system-tool.js +230 -0
  253. package/dist/tool-runtime/run-system-tool.js.map +1 -0
  254. package/dist/tool-runtime/tool-error.d.ts +6 -0
  255. package/dist/tool-runtime/tool-error.d.ts.map +1 -0
  256. package/dist/tool-runtime/tool-error.js +6 -0
  257. package/dist/tool-runtime/tool-error.js.map +1 -0
  258. package/dist/tool-runtime/worker-tools.d.ts +8 -0
  259. package/dist/tool-runtime/worker-tools.d.ts.map +1 -0
  260. package/dist/tool-runtime/worker-tools.js +65 -0
  261. package/dist/tool-runtime/worker-tools.js.map +1 -0
  262. package/dist/tool-runtime/write-admit.d.ts +21 -0
  263. package/dist/tool-runtime/write-admit.d.ts.map +1 -0
  264. package/dist/tool-runtime/write-admit.js +89 -0
  265. package/dist/tool-runtime/write-admit.js.map +1 -0
  266. package/package.json +114 -3
  267. package/policy/auto-mode-ask.scm +201 -0
  268. package/policy/bypass-detect.prompt +55 -0
  269. package/policy/classifier-bash-incomplete.prompt +46 -0
  270. package/policy/classifier-bash.prompt +45 -0
  271. package/policy/classifier-mcp.prompt +45 -0
  272. package/policy/classifier-read.prompt +44 -0
  273. package/policy/classifier-write-outside.prompt +46 -0
  274. package/policy/classifier-write-risky.prompt +45 -0
  275. package/policy/classifier-write-workspace.prompt +46 -0
  276. package/policy/classifier-write.prompt +45 -0
  277. package/policy/soft-deny-round1.prompt +51 -0
  278. package/policy/soft-deny-round2.prompt +60 -0
  279. package/src/agent-calls/acceptance.ts +71 -0
  280. package/src/agent-calls/callbacks.ts +75 -0
  281. package/src/agent-calls/delivery.ts +15 -0
  282. package/src/agent-calls/index.ts +16 -0
  283. package/src/agent-calls/operator.ts +99 -0
  284. package/src/agent-calls/runtime.ts +310 -0
  285. package/src/agent-calls/types.ts +33 -0
  286. package/src/context/compact-floors.ts +76 -0
  287. package/src/context/compact.ts +176 -0
  288. package/src/context/delivery.ts +15 -0
  289. package/src/context/history.ts +725 -0
  290. package/src/context/index.ts +35 -0
  291. package/src/context/observations.ts +13 -0
  292. package/src/context/retention/defaults.ts +58 -0
  293. package/src/context/retention/index.ts +45 -0
  294. package/src/context/retention/narrow.ts +123 -0
  295. package/src/context/retention/render.ts +177 -0
  296. package/src/context/retention/resolve.ts +306 -0
  297. package/src/context/retention/schema.ts +173 -0
  298. package/src/context/retention/stamp.ts +121 -0
  299. package/src/context/retention/step.ts +85 -0
  300. package/src/context/retention/view.ts +161 -0
  301. package/src/context/squeeze.ts +218 -0
  302. package/src/context/tools.ts +92 -0
  303. package/src/context/transcript.ts +705 -0
  304. package/src/policy-processor/README.md +43 -0
  305. package/src/policy-processor/bypass.ts +246 -0
  306. package/src/policy-processor/classifier.ts +711 -0
  307. package/src/policy-processor/cluster.ts +31 -0
  308. package/src/policy-processor/evidence.ts +214 -0
  309. package/src/policy-processor/explain.ts +310 -0
  310. package/src/policy-processor/index.ts +6 -0
  311. package/src/policy-processor/license.ts +45 -0
  312. package/src/policy-processor/peel-cwd.ts +1 -0
  313. package/src/policy-processor/real-path.ts +41 -0
  314. package/src/policy-processor/scope.ts +655 -0
  315. package/src/policy-processor/self-protect.ts +46 -0
  316. package/src/policy-processor/soft-deny.ts +225 -0
  317. package/src/policy-processor/unattended-guard.ts +158 -0
  318. package/src/session/cancel.ts +34 -0
  319. package/src/session/commands.ts +292 -0
  320. package/src/session/compact-actor.ts +132 -0
  321. package/src/session/compact-env.ts +539 -0
  322. package/src/session/compact.ts +95 -0
  323. package/src/session/index.ts +18 -0
  324. package/src/session/park.ts +73 -0
  325. package/src/session/side-channel-reminder.ts +148 -0
  326. package/src/session/types.ts +50 -0
  327. package/src/tool-catalog/catalog.ts +282 -0
  328. package/src/tool-catalog/index.ts +26 -0
  329. package/src/tool-catalog/recipes.ts +154 -0
  330. package/src/tool-catalog/types.ts +110 -0
  331. package/src/tool-runtime/approval/approved.ts +20 -0
  332. package/src/tool-runtime/approval/dist.ts +29 -0
  333. package/src/tool-runtime/approval/inbound.ts +50 -0
  334. package/src/tool-runtime/approval/unattended.ts +24 -0
  335. package/src/tool-runtime/blob-port.ts +64 -0
  336. package/src/tool-runtime/extra-root.ts +16 -0
  337. package/src/tool-runtime/handler.ts +576 -0
  338. package/src/tool-runtime/index.ts +21 -0
  339. package/src/tool-runtime/peel.ts +91 -0
  340. package/src/tool-runtime/plugin-context.ts +68 -0
  341. package/src/tool-runtime/recall.ts +104 -0
  342. package/src/tool-runtime/run-system-tool.ts +273 -0
  343. package/src/tool-runtime/tool-error.ts +6 -0
  344. package/src/tool-runtime/worker-tools.ts +76 -0
  345. package/src/tool-runtime/write-admit.ts +90 -0
  346. package/README.md +0 -3
@@ -0,0 +1,292 @@
1
+ /**
2
+ * Session commands: turn admit (mint/steer/queue/continue), compact, cancel,
3
+ * rewind, retry, and prompt-queue drain. Transport and document persistence
4
+ * stay on the host.
5
+ */
6
+ import { asSystemPrompt, asUserPrompt, type UserPrompt } from "@inhuman.tools/harness-commons";
7
+ import {
8
+ admitQueue,
9
+ admitSteer,
10
+ CompactJob,
11
+ findEvalTurnByRequestId,
12
+ findTurnById,
13
+ HOST_QUEUE_VERBS,
14
+ isAtTip,
15
+ isRewindPin,
16
+ looksLikePath,
17
+ onTipChain,
18
+ reactChunks,
19
+ ReACTChunk,
20
+ refreshSystemPrompt,
21
+ resolvedTip,
22
+ SessionSystemPrompt,
23
+ SessionTurn,
24
+ skillMatchesVerb,
25
+ tapeCompletion,
26
+ userVisualsJson,
27
+ type UserVisualIdentity,
28
+ } from "@inhuman.tools/harness-model";
29
+
30
+ import type { SessionCommandHost } from "./types.js";
31
+ import { compactRejectReason, stampCompactInputs } from "../context/index.js";
32
+
33
+ export type CommandFail = {
34
+ readonly ok: false;
35
+ readonly reason: string;
36
+ readonly invalid?: boolean;
37
+ };
38
+
39
+ export type TurnAdmitResult =
40
+ | {
41
+ readonly ok: true;
42
+ readonly action: "noop" | "mint" | "steer" | "queue" | "continue";
43
+ }
44
+ | CommandFail;
45
+
46
+ export type CompactAdmitResult = { readonly ok: true; readonly compacted: false } | CommandFail;
47
+
48
+ export type RewindResult = { readonly ok: true; readonly turnId: string } | CommandFail;
49
+
50
+ export type CancelTurnArgs = { readonly turnId: string } | { readonly requestId: string };
51
+
52
+ type TurnKind = "steer" | "queue" | "continue";
53
+
54
+ function requestTurnCancel(turn: SessionTurn, requestId?: string, cancelledEval?: Record<string, string>): void {
55
+ turn.cancelRequested = true;
56
+ if (requestId != null && requestId !== "" && cancelledEval != null) {
57
+ cancelledEval[requestId] = "1";
58
+ }
59
+ }
60
+
61
+ function refreshTurn(host: SessionCommandHost, turn: SessionTurn): void {
62
+ refreshSystemPrompt(turn, {
63
+ constitution: asSystemPrompt(host.constitution),
64
+ env: host.env(),
65
+ });
66
+ host.applyBotNotice?.(turn);
67
+ }
68
+
69
+ /** R1: the policy in force when the turn is minted. A later config or kv edit applies from the next turn. */
70
+ function retentionStamp(host: SessionCommandHost): { readonly retentionJson?: string } {
71
+ const json = host.retentionJson?.() ?? "";
72
+ return json === "" ? {} : { retentionJson: json };
73
+ }
74
+
75
+ function mintContinueTurn(host: SessionCommandHost, head: SessionTurn): void {
76
+ const turn = new SessionTurn({
77
+ turnTail: head,
78
+ prompt: asUserPrompt(""),
79
+ queue: [new ReACTChunk()],
80
+ toolsDefinition: host.toolsFor(head),
81
+ ...retentionStamp(host),
82
+ });
83
+ host.session.seatHead(turn);
84
+ refreshTurn(host, turn);
85
+ host.log?.("continue admitted");
86
+ }
87
+
88
+ function skillSplit(
89
+ host: SessionCommandHost,
90
+ text: UserPrompt,
91
+ ): { readonly prompt: UserPrompt; readonly derived: UserPrompt | null } {
92
+ host.syncSkills?.();
93
+ return host.expandSkill?.(text, host.session.skills, host.queuedVerbs()) ?? { prompt: text, derived: null };
94
+ }
95
+
96
+ function mintUserTurn(
97
+ host: SessionCommandHost,
98
+ text: UserPrompt,
99
+ visuals: readonly UserVisualIdentity[] = [],
100
+ ): SessionTurn {
101
+ const split = skillSplit(host, text);
102
+ const tail =
103
+ host.session.head ??
104
+ new SessionSystemPrompt({
105
+ constitution: asSystemPrompt(host.constitution),
106
+ env: host.env(),
107
+ skills: host.session.skills.map((skill) => skill.clone()),
108
+ });
109
+ const turn = new SessionTurn({
110
+ turnTail: tail,
111
+ prompt: split.prompt,
112
+ derivedMessage: split.derived,
113
+ toolsDefinition: host.toolsFor(tail),
114
+ ...retentionStamp(host),
115
+ ...(visuals.length === 0 ? {} : { visualsJson: userVisualsJson(visuals) }),
116
+ });
117
+ turn.markStarted();
118
+ host.session.seatHead(turn);
119
+ refreshTurn(host, turn);
120
+ host.log?.(`turn ${text}`);
121
+ return turn;
122
+ }
123
+
124
+ function mintCompactTurn(host: SessionCommandHost, focus: string): CompactAdmitResult {
125
+ if (host.session.head == null) {
126
+ host.log?.("compact no-head");
127
+ return { ok: false, reason: "no-head" };
128
+ }
129
+ const rejected = compactRejectReason(host.session.head);
130
+ if (rejected != null) {
131
+ host.log?.(`compact ${rejected}`);
132
+ return { ok: false, reason: rejected };
133
+ }
134
+ const job = new CompactJob({ reason: "user" });
135
+ // F8: the cut's inputs are facts of this job from here on, not live settings.
136
+ stampCompactInputs(job, host.compactKeepTurns?.() ?? 1, host.session.kvs);
137
+ const turn = new SessionTurn({
138
+ turnTail: host.session.head,
139
+ prompt: asUserPrompt(focus),
140
+ queue: [job],
141
+ reloadTools: true,
142
+ });
143
+ turn.pushChild(job);
144
+ turn.markStarted();
145
+ host.session.seatHead(turn);
146
+ refreshTurn(host, turn);
147
+ host.log?.("compact admitted");
148
+ return { ok: true, compacted: false };
149
+ }
150
+
151
+ export function admitTurn(
152
+ host: SessionCommandHost,
153
+ args: { readonly prompt: string; readonly kind?: TurnKind; readonly visuals?: readonly UserVisualIdentity[] },
154
+ ): TurnAdmitResult {
155
+ const visuals = args.visuals ?? [];
156
+ const prompt = asUserPrompt(args.prompt.trim());
157
+ if (visuals.length > 0 && (args.kind === "steer" || args.kind === "queue" || args.kind === "continue")) {
158
+ return { ok: false, reason: "an image can't be sent with that", invalid: true };
159
+ }
160
+ if (args.kind === "continue") {
161
+ if (host.session.findRunningTurn() != null) return { ok: true, action: "noop" };
162
+ if (!isAtTip(host.session.head, host.session.tip)) {
163
+ return { ok: false, reason: "off-tip", invalid: true };
164
+ }
165
+ const head = host.session.head;
166
+ if (!head?.lastTurnIncomplete) return { ok: true, action: "noop" };
167
+ if ((host.session.kvs.connection ?? "").trim() === "") {
168
+ return { ok: false, reason: "connection is required", invalid: true };
169
+ }
170
+ mintContinueTurn(host, head);
171
+ return { ok: true, action: "continue" };
172
+ }
173
+ if (prompt === "" && visuals.length === 0) return { ok: true, action: "noop" };
174
+ if ((host.session.kvs.connection ?? "").trim() === "") {
175
+ return { ok: false, reason: "connection is required", invalid: true };
176
+ }
177
+ const running = host.session.findRunningTurn();
178
+ if (running != null) {
179
+ if (visuals.length > 0) return { ok: false, reason: "an image can't be sent with that", invalid: true };
180
+ // A steer is an expectation that the turn claims it at its next round.
181
+ // A turn that can't (stopped, an eval, a compact) won't, so the row is
182
+ // an expectation of a future turn instead: the queue lane, which the
183
+ // session mints from once that turn has exited.
184
+ const kind = args.kind !== "queue" && host.session.steerTurn === running ? "steer" : "queue";
185
+ const split = skillSplit(host, prompt);
186
+ if (kind === "queue") admitQueue(host.session, split.prompt, running.uuid, split.derived);
187
+ else admitSteer(host.session, split.prompt, running.uuid, split.derived);
188
+ host.log?.(`turn ${kind} ${prompt}`);
189
+ return { ok: true, action: kind };
190
+ }
191
+ mintUserTurn(host, prompt, visuals);
192
+ return { ok: true, action: "mint" };
193
+ }
194
+
195
+ export function admitCompact(host: SessionCommandHost, focus = ""): CompactAdmitResult {
196
+ if (host.session.findRunningTurn() != null) {
197
+ return { ok: false, reason: "already running", invalid: true };
198
+ }
199
+ return mintCompactTurn(host, focus);
200
+ }
201
+
202
+ export function cancelTurnCommand(host: SessionCommandHost, args: CancelTurnArgs): { readonly ok: true } {
203
+ if ("requestId" in args) {
204
+ const existing = findEvalTurnByRequestId(host.session, args.requestId);
205
+ if (existing != null) {
206
+ requestTurnCancel(existing, args.requestId, host.session.cancelledEvalRequests);
207
+ host.cancelOwned(existing);
208
+ } else {
209
+ host.session.cancelledEvalRequests[args.requestId] = "1";
210
+ }
211
+ host.log?.(`turn/cancel request ${args.requestId}`);
212
+ return { ok: true };
213
+ }
214
+ const turn = findTurnById(host.session, args.turnId) ?? host.loadTurn?.(args.turnId);
215
+ if (turn instanceof SessionTurn) {
216
+ requestTurnCancel(turn, turn.evalSpec?.requestId, host.session.cancelledEvalRequests);
217
+ host.cancelOwned(turn);
218
+ }
219
+ host.log?.(`turn/cancel turn ${args.turnId}`);
220
+ return { ok: true };
221
+ }
222
+
223
+ export function rewindTurn(host: SessionCommandHost, turnId: string): RewindResult {
224
+ const live = host.session.head;
225
+ if (live == null) return { ok: false, reason: "no-head", invalid: true };
226
+ const loaded = host.loadTurn?.(turnId) ?? findTurnById(host.session, turnId);
227
+ if (!(loaded instanceof SessionTurn)) return { ok: false, reason: "unknown-id", invalid: true };
228
+ const ceiling = resolvedTip(live, host.session.tip);
229
+ if (!isRewindPin(loaded) && loaded !== ceiling) return { ok: false, reason: "not-a-pin", invalid: true };
230
+ if (!onTipChain(loaded, ceiling, live)) return { ok: false, reason: "off-chain", invalid: true };
231
+ const open = host.session.liveChain.filter((turn) => turn.inLoop);
232
+ host.session.rewindHead(loaded, ceiling);
233
+ for (const turn of open) {
234
+ requestTurnCancel(turn, turn.evalSpec?.requestId, host.session.cancelledEvalRequests);
235
+ host.cancelOwned(turn);
236
+ }
237
+ host.restorePluginState?.();
238
+ host.log?.(`turn/rewind ${turnId}`);
239
+ return { ok: true, turnId: loaded.uuid };
240
+ }
241
+
242
+ export function retryTurn(host: SessionCommandHost): { readonly ok: true } {
243
+ const turn = host.session.findRunningTurn();
244
+ if (turn != null) {
245
+ const live = reactChunks(turn)
246
+ .map((chunk) => tapeCompletion(chunk))
247
+ .filter((pew) => pew != null && pew.outcome == null);
248
+ const completion = live.at(-1);
249
+ if (completion != null) host.skipBackoff?.(completion);
250
+ }
251
+ host.log?.("turn/retry");
252
+ return { ok: true };
253
+ }
254
+
255
+ export function drainPromptQueue(host: SessionCommandHost): void {
256
+ if (host.closed) return;
257
+ if (host.session.findRunningTurn() != null) return;
258
+ const item = host.session.promptQueue[0];
259
+ if (item == null) return;
260
+ host.syncSkills?.();
261
+ const trimmed = item.text.trim();
262
+ if (!looksLikePath(trimmed) && trimmed.startsWith("/")) {
263
+ const token = (trimmed.split("\n")[0] ?? "").trim().split(/\s/)[0] ?? "";
264
+ const verb = token.startsWith("/") && token.length >= 2 ? token.slice(1) : null;
265
+ if (verb === "compact") {
266
+ host.session.promptQueue.shift();
267
+ mintCompactTurn(host, trimmed.slice(trimmed.indexOf("compact") + "compact".length).trim());
268
+ return;
269
+ }
270
+ if (verb === "rename") {
271
+ host.session.promptQueue.shift();
272
+ const rest = trimmed.slice(trimmed.indexOf("rename") + "rename".length).trim();
273
+ host.rename?.(rest === "--auto" ? "" : rest);
274
+ drainPromptQueue(host);
275
+ return;
276
+ }
277
+ const verbs = new Set<string>([...HOST_QUEUE_VERBS, ...host.queuedVerbs()]);
278
+ if (verb !== null && verbs.has(verb)) {
279
+ host.session.promptQueue.shift();
280
+ host.log?.(`queue reject host-verb ${item.text}`);
281
+ return;
282
+ }
283
+ if (verb !== null && !host.session.skills.some((skill) => skillMatchesVerb(skill, verb))) {
284
+ host.session.promptQueue.shift();
285
+ host.log?.(`queue reject unknown-command ${item.text}`);
286
+ return;
287
+ }
288
+ }
289
+ if ((host.session.kvs.connection ?? "").trim() === "") return;
290
+ host.session.promptQueue.shift();
291
+ mintUserTurn(host, asUserPrompt(trimmed));
292
+ }
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Compact cases of the turn loop. Calculations come from context; the
3
+ * Scheme compact is `applyCompact`.
4
+ */
5
+ import type { PromptComplete } from "@inhuman.tools/env-capability-module-prompt";
6
+ import {
7
+ CompactJob,
8
+ liveBackgroundJobs,
9
+ liveJobsCheckIn,
10
+ SessionRoot,
11
+ SessionTurn,
12
+ } from "@inhuman.tools/harness-model";
13
+
14
+ import { applyCompact } from "./compact-env.js";
15
+ import { loadCompactProgram, type CompactProgram } from "./compact.js";
16
+ import {
17
+ compactRejectReason,
18
+ historyBehind,
19
+ keepFloorsOfJob,
20
+ sliceCompactZones,
21
+ stampCompactInputs,
22
+ textOfCell,
23
+ Transcript,
24
+ } from "../context/index.js";
25
+
26
+ /** Human tape only. Not injected into the next model prompt. */
27
+ const COMPACT_FAILED_NOTICE = "couldn't compact — try again later";
28
+
29
+ export type CompactHost = {
30
+ readonly turn: SessionTurn;
31
+ readonly session: SessionRoot;
32
+ readonly compactKeepTurns: number;
33
+ readonly compactStrategy: string;
34
+ readonly kernelFsRoot: string;
35
+ readonly connectionId: string;
36
+ readonly model: string;
37
+ complete?: PromptComplete;
38
+ loadProgram?: (spec: string | undefined, kernelFsRoot: string) => CompactProgram;
39
+ log?: (message: string) => void;
40
+ fail?: (label: string, error: unknown) => void;
41
+ };
42
+
43
+ function compactRead(
44
+ configFloor: number,
45
+ kv: Readonly<Record<string, string>>,
46
+ ): {
47
+ readonly configFloor: number;
48
+ readonly kv: Readonly<Record<string, string>>;
49
+ } {
50
+ return { configFloor: Math.max(configFloor, 1), kv };
51
+ }
52
+
53
+ function failCompact(job: CompactJob): void {
54
+ job.failed = true;
55
+ job.notice = COMPACT_FAILED_NOTICE;
56
+ job.standIn = "";
57
+ job.markComplete();
58
+ }
59
+
60
+ function loadStrategy(host: CompactHost): CompactProgram {
61
+ return (host.loadProgram ?? loadCompactProgram)(host.compactStrategy, host.kernelFsRoot);
62
+ }
63
+
64
+ /** Abort leaves the job open: an incomplete compact is not a cutoff, and its owner settles it. */
65
+ export async function runCompactJob(job: CompactJob, host: CompactHost, signal?: AbortSignal): Promise<void> {
66
+ const rejected = compactRejectReason(host.turn);
67
+ if (rejected != null) {
68
+ host.log?.(`compact ${rejected}`);
69
+ job.markComplete();
70
+ return;
71
+ }
72
+ try {
73
+ const session = host.session;
74
+ const read = compactRead(host.compactKeepTurns, session.kvs);
75
+ const eat = Transcript.fromCells(historyBehind(host.turn, read));
76
+ const need = host.turn.contextNeed;
77
+ // The job's cut comes from the settings recorded on it (F8). An unstamped
78
+ // job is stamped here, on its first run, and keeps that reading for good.
79
+ if (job.keepTurns == null) stampCompactInputs(job, read.configFloor, session.kvs);
80
+ const floors = keepFloorsOfJob(job, need, { kv: session.kvs, configFloor: read.configFloor });
81
+ const zones = sliceCompactZones(eat, floors);
82
+ if (zones.prefix.cells.length === 0) {
83
+ host.log?.("compact keep-all");
84
+ job.markComplete();
85
+ return;
86
+ }
87
+ const focus = job.reason === "user" ? host.turn.prompt.trim() || need?.focus || "" : (need?.focus ?? "");
88
+ const strategy = loadStrategy(host);
89
+ if (strategy.failsafe != null) {
90
+ // Keep-first is a failsafe, not a strategy: it keeps one cell and drops the
91
+ // rest. Say so, or a broken install looks like a working compaction.
92
+ host.fail?.("compact failsafe", `no compaction program loaded (${strategy.failsafe}); using keep-first`);
93
+ host.log?.(`compact failsafe: ${strategy.failsafe}`);
94
+ }
95
+ const result = await applyCompact(strategy.source, zones.prefix, eat, {
96
+ reason: job.reason,
97
+ focus,
98
+ kv: session.kvs,
99
+ forced: job.reason === "user",
100
+ sourcePath: strategy.sourcePath,
101
+ job: host.turn,
102
+ complete: host.complete,
103
+ connectionId: host.connectionId === "" ? undefined : host.connectionId,
104
+ completionModel: host.model === "" ? undefined : host.model,
105
+ signal,
106
+ });
107
+ if (!result.ok) {
108
+ host.fail?.("compact strategy", result.reason);
109
+ failCompact(job);
110
+ return;
111
+ }
112
+ const jobs = liveJobsCheckIn(await liveBackgroundJobs(session.motionWork()));
113
+ const body = result.checkIn
114
+ .map((cell) => textOfCell(cell).trim())
115
+ .filter((line) => line !== "")
116
+ .join("\n\n");
117
+ const checkIn = [jobs, body].filter((line) => line !== "").join("\n\n");
118
+ if (checkIn === "") {
119
+ host.fail?.("compact strategy", "empty-check-in");
120
+ failCompact(job);
121
+ return;
122
+ }
123
+ job.standIn = checkIn;
124
+ job.failed = false;
125
+ job.notice = "";
126
+ job.markComplete();
127
+ } catch (error) {
128
+ if (signal?.aborted) return;
129
+ host.fail?.("compact strategy", error);
130
+ failCompact(job);
131
+ }
132
+ }