nodal-agents 0.9.1 → 0.9.2

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 (190) hide show
  1. package/cli.js +404 -47
  2. package/docs-index.json +12 -12
  3. package/migrations/0122_entities_drop_memory_curation_enabled.sql +17 -0
  4. package/migrations/meta/_journal.json +7 -0
  5. package/package.json +1 -1
  6. package/runner.js +459 -98
  7. package/web/.next/BUILD_ID +1 -1
  8. package/web/.next/build-manifest.json +2 -2
  9. package/web/.next/prerender-manifest.json +3 -3
  10. package/web/.next/server/app/(dashboard)/agents/[id]/channels/page.js +1 -1
  11. package/web/.next/server/app/(dashboard)/agents/[id]/channels/page_client-reference-manifest.js +1 -1
  12. package/web/.next/server/app/(dashboard)/agents/[id]/edit/page.js +2 -2
  13. package/web/.next/server/app/(dashboard)/agents/[id]/edit/page_client-reference-manifest.js +1 -1
  14. package/web/.next/server/app/(dashboard)/agents/[id]/telegram/page.js +1 -1
  15. package/web/.next/server/app/(dashboard)/agents/[id]/telegram/page_client-reference-manifest.js +1 -1
  16. package/web/.next/server/app/(dashboard)/agents/page.js +1 -1
  17. package/web/.next/server/app/(dashboard)/agents/page_client-reference-manifest.js +1 -1
  18. package/web/.next/server/app/(dashboard)/approvals/page.js +1 -1
  19. package/web/.next/server/app/(dashboard)/approvals/page_client-reference-manifest.js +1 -1
  20. package/web/.next/server/app/(dashboard)/automations/[id]/page.js +1 -1
  21. package/web/.next/server/app/(dashboard)/automations/[id]/page_client-reference-manifest.js +1 -1
  22. package/web/.next/server/app/(dashboard)/automations/page.js +1 -1
  23. package/web/.next/server/app/(dashboard)/automations/page_client-reference-manifest.js +1 -1
  24. package/web/.next/server/app/(dashboard)/chat/[id]/page.js +1 -1
  25. package/web/.next/server/app/(dashboard)/chat/[id]/page_client-reference-manifest.js +1 -1
  26. package/web/.next/server/app/(dashboard)/chat/page.js +1 -1
  27. package/web/.next/server/app/(dashboard)/chat/page_client-reference-manifest.js +1 -1
  28. package/web/.next/server/app/(dashboard)/code/[id]/page.js +1 -1
  29. package/web/.next/server/app/(dashboard)/code/[id]/page_client-reference-manifest.js +1 -1
  30. package/web/.next/server/app/(dashboard)/code/page.js +1 -1
  31. package/web/.next/server/app/(dashboard)/code/page_client-reference-manifest.js +1 -1
  32. package/web/.next/server/app/(dashboard)/connectors/page.js +1 -1
  33. package/web/.next/server/app/(dashboard)/connectors/page_client-reference-manifest.js +1 -1
  34. package/web/.next/server/app/(dashboard)/credentials/page.js +1 -1
  35. package/web/.next/server/app/(dashboard)/credentials/page_client-reference-manifest.js +1 -1
  36. package/web/.next/server/app/(dashboard)/dashboard/page.js +1 -1
  37. package/web/.next/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
  38. package/web/.next/server/app/(dashboard)/jobs/[id]/page.js +1 -1
  39. package/web/.next/server/app/(dashboard)/jobs/[id]/page_client-reference-manifest.js +1 -1
  40. package/web/.next/server/app/(dashboard)/jobs/page.js +1 -1
  41. package/web/.next/server/app/(dashboard)/jobs/page_client-reference-manifest.js +1 -1
  42. package/web/.next/server/app/(dashboard)/learned-skills/page.js +1 -1
  43. package/web/.next/server/app/(dashboard)/learned-skills/page_client-reference-manifest.js +1 -1
  44. package/web/.next/server/app/(dashboard)/llm-providers/page.js +1 -1
  45. package/web/.next/server/app/(dashboard)/llm-providers/page_client-reference-manifest.js +1 -1
  46. package/web/.next/server/app/(dashboard)/logs/page.js +1 -1
  47. package/web/.next/server/app/(dashboard)/logs/page_client-reference-manifest.js +1 -1
  48. package/web/.next/server/app/(dashboard)/mcp/page.js +1 -1
  49. package/web/.next/server/app/(dashboard)/mcp/page_client-reference-manifest.js +1 -1
  50. package/web/.next/server/app/(dashboard)/memories/page.js +1 -1
  51. package/web/.next/server/app/(dashboard)/memories/page_client-reference-manifest.js +1 -1
  52. package/web/.next/server/app/(dashboard)/page.js +1 -1
  53. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  54. package/web/.next/server/app/(dashboard)/scheduled/[id]/page.js +1 -1
  55. package/web/.next/server/app/(dashboard)/scheduled/[id]/page_client-reference-manifest.js +1 -1
  56. package/web/.next/server/app/(dashboard)/scheduled/page.js +1 -1
  57. package/web/.next/server/app/(dashboard)/scheduled/page_client-reference-manifest.js +1 -1
  58. package/web/.next/server/app/(dashboard)/settings/page.js +1 -1
  59. package/web/.next/server/app/(dashboard)/settings/page_client-reference-manifest.js +1 -1
  60. package/web/.next/server/app/(dashboard)/settings/root-context/page.js +1 -1
  61. package/web/.next/server/app/(dashboard)/settings/root-context/page_client-reference-manifest.js +1 -1
  62. package/web/.next/server/app/(dashboard)/skills/[id]/edit/page.js +1 -1
  63. package/web/.next/server/app/(dashboard)/skills/[id]/edit/page_client-reference-manifest.js +1 -1
  64. package/web/.next/server/app/(dashboard)/skills/new/page.js +1 -1
  65. package/web/.next/server/app/(dashboard)/skills/new/page_client-reference-manifest.js +1 -1
  66. package/web/.next/server/app/(dashboard)/skills/page.js +1 -1
  67. package/web/.next/server/app/(dashboard)/skills/page_client-reference-manifest.js +1 -1
  68. package/web/.next/server/app/(dashboard)/spaces/[id]/files/page.js +1 -1
  69. package/web/.next/server/app/(dashboard)/spaces/[id]/files/page_client-reference-manifest.js +1 -1
  70. package/web/.next/server/app/(dashboard)/spaces/[id]/page.js +1 -1
  71. package/web/.next/server/app/(dashboard)/spaces/[id]/page_client-reference-manifest.js +1 -1
  72. package/web/.next/server/app/(dashboard)/spaces/page.js +1 -1
  73. package/web/.next/server/app/(dashboard)/spaces/page_client-reference-manifest.js +1 -1
  74. package/web/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  75. package/web/.next/server/app/_global-error.html +1 -1
  76. package/web/.next/server/app/_global-error.rsc +2 -2
  77. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +2 -2
  78. package/web/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +2 -2
  79. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  80. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  81. package/web/.next/server/app/_not-found.html +1 -1
  82. package/web/.next/server/app/_not-found.rsc +2 -2
  83. package/web/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  84. package/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  85. package/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  86. package/web/.next/server/app/login/page.js +1 -1
  87. package/web/.next/server/app/login/page_client-reference-manifest.js +1 -1
  88. package/web/.next/server/app/onboarding/page.js +2 -2
  89. package/web/.next/server/app/onboarding/page_client-reference-manifest.js +1 -1
  90. package/web/.next/server/chunks/1960.js +1 -0
  91. package/web/.next/server/chunks/{4208.js → 2096.js} +1 -1
  92. package/web/.next/server/chunks/292.js +1 -0
  93. package/web/.next/server/chunks/3675.js +1 -1
  94. package/web/.next/server/chunks/409.js +1 -1
  95. package/web/.next/server/chunks/42.js +2 -2
  96. package/web/.next/server/chunks/494.js +1 -1
  97. package/web/.next/server/chunks/5547.js +1 -0
  98. package/web/.next/server/chunks/570.js +1 -0
  99. package/web/.next/server/chunks/5804.js +1 -1
  100. package/web/.next/server/chunks/5974.js +1 -0
  101. package/web/.next/server/chunks/6106.js +1 -0
  102. package/web/.next/server/chunks/692.js +6 -6
  103. package/web/.next/server/chunks/7134.js +3 -3
  104. package/web/.next/server/chunks/7431.js +1 -0
  105. package/web/.next/server/chunks/7533.js +1 -0
  106. package/web/.next/server/chunks/7915.js +1 -1
  107. package/web/.next/server/chunks/8022.js +1 -1
  108. package/web/.next/server/chunks/8536.js +3 -0
  109. package/web/.next/server/chunks/8974.js +13 -13
  110. package/web/.next/server/chunks/9200.js +1 -0
  111. package/web/.next/server/middleware-build-manifest.js +1 -1
  112. package/web/.next/server/middleware.js +2 -2
  113. package/web/.next/server/pages/404.html +1 -1
  114. package/web/.next/server/pages/500.html +1 -1
  115. package/web/.next/server/server-reference-manifest.js +1 -1
  116. package/web/.next/server/server-reference-manifest.json +1 -1
  117. package/web/.next/static/chunks/1054-08930540869affcc.js +1 -0
  118. package/web/.next/static/chunks/1091-6d0af9f18ddf99f6.js +1 -0
  119. package/web/.next/static/chunks/{1332-0e4a72eac08cebb9.js → 1332-c8bed6b750598652.js} +1 -1
  120. package/web/.next/static/chunks/{3051-466a9da3e351fd0d.js → 3051-26ddd67461f743c4.js} +1 -1
  121. package/web/.next/static/chunks/3159-f25525771781f5aa.js +1 -0
  122. package/web/.next/static/chunks/3775-3a5a749d63c785a1.js +3 -0
  123. package/web/.next/static/chunks/390-d6132d3a117487df.js +1 -0
  124. package/web/.next/static/chunks/4020-9778230f3cc2164a.js +1 -0
  125. package/web/.next/static/chunks/{5034-11fd1b56b43dc6e5.js → 5034-fc9997ff33a114aa.js} +1 -1
  126. package/web/.next/static/chunks/7879-67ac5a52d74c20d2.js +1 -0
  127. package/web/.next/static/chunks/9643-e9c8a744dd98813d.js +1 -0
  128. package/web/.next/static/chunks/9952-992cabfb077d287c.js +1 -0
  129. package/web/.next/static/chunks/app/(dashboard)/agents/[id]/edit/page-5ca9c1eef4d0f837.js +6 -0
  130. package/web/.next/static/chunks/app/(dashboard)/agents/page-5ffa4a2468c1f95a.js +1 -0
  131. package/web/.next/static/chunks/app/(dashboard)/approvals/{page-3de0cc34d6dbeaf5.js → page-cd46d5e439a20d3e.js} +1 -1
  132. package/web/.next/static/chunks/app/(dashboard)/automations/[id]/{page-bebc71312e736828.js → page-9ef1d76121b6030d.js} +1 -1
  133. package/web/.next/static/chunks/app/(dashboard)/automations/page-46eeaa40df9e58f8.js +1 -0
  134. package/web/.next/static/chunks/app/(dashboard)/chat/[id]/{page-faa53d8decd24a6a.js → page-25e095bf0cdd1c40.js} +1 -1
  135. package/web/.next/static/chunks/app/(dashboard)/chat/page-e2df1a328e18da7a.js +1 -0
  136. package/web/.next/static/chunks/app/(dashboard)/code/[id]/{page-52a3e2140bd0d64a.js → page-f5f7624cfbb32ee2.js} +1 -1
  137. package/web/.next/static/chunks/app/(dashboard)/connectors/page-2ecbfc5836577888.js +1 -0
  138. package/web/.next/static/chunks/app/(dashboard)/dashboard/{page-5002d088b635d8f9.js → page-7473d1190864cbd4.js} +1 -1
  139. package/web/.next/static/chunks/app/(dashboard)/jobs/[id]/{page-5573e316921e5315.js → page-47e177ab46926fd7.js} +1 -1
  140. package/web/.next/static/chunks/app/(dashboard)/layout-0b429859260736b2.js +1 -0
  141. package/web/.next/static/chunks/app/(dashboard)/learned-skills/page-596d973a31e774db.js +1 -0
  142. package/web/.next/static/chunks/app/(dashboard)/llm-providers/page-ba1968c9430c4dd4.js +1 -0
  143. package/web/.next/static/chunks/app/(dashboard)/logs/page-f74da6f66116c7e7.js +1 -0
  144. package/web/.next/static/chunks/app/(dashboard)/mcp/page-07bdc6780b13cfca.js +1 -0
  145. package/web/.next/static/chunks/app/(dashboard)/memories/page-593161bc7c2a25d7.js +1 -0
  146. package/web/.next/static/chunks/app/(dashboard)/page-889d6e89a8f679f8.js +1 -0
  147. package/web/.next/static/chunks/app/(dashboard)/scheduled/[id]/{page-5573e316921e5315.js → page-47e177ab46926fd7.js} +1 -1
  148. package/web/.next/static/chunks/app/(dashboard)/settings/page-1b40e127c38affda.js +1 -0
  149. package/web/.next/static/chunks/app/(dashboard)/settings/root-context/page-6b7e1cffcad40a6a.js +1 -0
  150. package/web/.next/static/chunks/app/(dashboard)/skills/page-3ad87d1a3fbb4f05.js +1 -0
  151. package/web/.next/static/chunks/app/(dashboard)/spaces/page-9dbb35822503481b.js +1 -0
  152. package/web/.next/static/chunks/app/login/{page-031e915b40cb5be6.js → page-5357f030e5018563.js} +1 -1
  153. package/web/.next/static/chunks/app/onboarding/{page-06209a6e3a31fb73.js → page-9b6955cdd3033584.js} +2 -2
  154. package/web/.next/server/chunks/3650.js +0 -1
  155. package/web/.next/server/chunks/385.js +0 -1
  156. package/web/.next/server/chunks/4194.js +0 -1
  157. package/web/.next/server/chunks/616.js +0 -1
  158. package/web/.next/server/chunks/6724.js +0 -1
  159. package/web/.next/server/chunks/7190.js +0 -1
  160. package/web/.next/server/chunks/7273.js +0 -3
  161. package/web/.next/server/chunks/7416.js +0 -1
  162. package/web/.next/server/chunks/7975.js +0 -1
  163. package/web/.next/server/chunks/8153.js +0 -1
  164. package/web/.next/static/chunks/1054-5f8b510bbf6ff3e9.js +0 -1
  165. package/web/.next/static/chunks/1091-8f1b68252431e271.js +0 -1
  166. package/web/.next/static/chunks/3388-530c6d429c484862.js +0 -3
  167. package/web/.next/static/chunks/3815-aa88c216677b6c3f.js +0 -1
  168. package/web/.next/static/chunks/4020-dcde3e62f67473f3.js +0 -1
  169. package/web/.next/static/chunks/6883-73dc26cf02070115.js +0 -1
  170. package/web/.next/static/chunks/7039-7a3b6bdbfda78038.js +0 -1
  171. package/web/.next/static/chunks/9643-b0b049bb41a7cba4.js +0 -1
  172. package/web/.next/static/chunks/9901-24977d0da68dcf77.js +0 -1
  173. package/web/.next/static/chunks/app/(dashboard)/agents/[id]/edit/page-4594e5fc99cc04ed.js +0 -6
  174. package/web/.next/static/chunks/app/(dashboard)/agents/page-a26d15238b4c55d3.js +0 -1
  175. package/web/.next/static/chunks/app/(dashboard)/automations/page-04c38b0a633b5c94.js +0 -1
  176. package/web/.next/static/chunks/app/(dashboard)/chat/page-c45d840d7ca4faa7.js +0 -1
  177. package/web/.next/static/chunks/app/(dashboard)/connectors/page-081ca4b9bbeb2fcb.js +0 -1
  178. package/web/.next/static/chunks/app/(dashboard)/layout-b542af6fe3f7621e.js +0 -1
  179. package/web/.next/static/chunks/app/(dashboard)/learned-skills/page-950bf08720e4b3aa.js +0 -1
  180. package/web/.next/static/chunks/app/(dashboard)/llm-providers/page-8ada985ee9578d2f.js +0 -1
  181. package/web/.next/static/chunks/app/(dashboard)/logs/page-a2cf705f0ddb7329.js +0 -1
  182. package/web/.next/static/chunks/app/(dashboard)/mcp/page-17498336e813cd6c.js +0 -1
  183. package/web/.next/static/chunks/app/(dashboard)/memories/page-5c8fc395823f4823.js +0 -1
  184. package/web/.next/static/chunks/app/(dashboard)/page-48d1d32604854d18.js +0 -1
  185. package/web/.next/static/chunks/app/(dashboard)/settings/page-f4d50d3900c7387a.js +0 -1
  186. package/web/.next/static/chunks/app/(dashboard)/settings/root-context/page-edace0d3a7f0134a.js +0 -1
  187. package/web/.next/static/chunks/app/(dashboard)/skills/page-7dc32162faa0e762.js +0 -1
  188. package/web/.next/static/chunks/app/(dashboard)/spaces/page-b516d5b0664dffee.js +0 -1
  189. /package/web/.next/static/{bG6cdQqQw9o06-WZ6DrN2 → x5fvzE6AeZGASlemQTLwd}/_buildManifest.js +0 -0
  190. /package/web/.next/static/{bG6cdQqQw9o06-WZ6DrN2 → x5fvzE6AeZGASlemQTLwd}/_ssgManifest.js +0 -0
package/runner.js CHANGED
@@ -2122,17 +2122,6 @@ var init_model_catalog = __esm({
2122
2122
  cacheWritePerMillionUsd: 6.25
2123
2123
  }
2124
2124
  },
2125
- {
2126
- modelId: "anthropic/claude-opus-5-fast",
2127
- label: "Claude Opus 5 (fast)",
2128
- capabilities: {
2129
- tools: true,
2130
- forcedToolChoice: true,
2131
- reasoningControl: { kind: "effort", levels: ["low", "medium", "high", "max"] }
2132
- },
2133
- contextWindow: 1e6,
2134
- pricing: { inputPerMillionUsd: 10, outputPerMillionUsd: 50 }
2135
- },
2136
2125
  {
2137
2126
  modelId: "anthropic/claude-sonnet-5",
2138
2127
  label: "Claude Sonnet 5",
@@ -2165,6 +2154,34 @@ var init_model_catalog = __esm({
2165
2154
  cacheWritePerMillionUsd: 12.5
2166
2155
  }
2167
2156
  },
2157
+ {
2158
+ // The newest of the family (2026-09-01), read off /api/v1/models on
2159
+ // 2026-09-22: same window, prices and modalities as Fable 5 except the
2160
+ // cache READ price, four times lower (0.25 vs 1). Its `reasoning` object
2161
+ // says mandatory:true with efforts max/xhigh/high/medium/low, so Off is
2162
+ // hidden here — the Fable 5 entry above predates that object and still
2163
+ // offers it (#417). No always-on `reasoning` flag, as for every Claude
2164
+ // route in this file: the flag would flip openrouter.ts's default
2165
+ // injection, and a mandatory model thinks anyway.
2166
+ modelId: "anthropic/claude-fable-5.1",
2167
+ label: "Claude Fable 5.1",
2168
+ capabilities: {
2169
+ tools: true,
2170
+ forcedToolChoice: true,
2171
+ reasoningControl: {
2172
+ kind: "effort",
2173
+ levels: ["low", "medium", "high", "max"],
2174
+ mandatory: true
2175
+ }
2176
+ },
2177
+ contextWindow: 1e6,
2178
+ pricing: {
2179
+ inputPerMillionUsd: 10,
2180
+ outputPerMillionUsd: 50,
2181
+ cacheReadPerMillionUsd: 0.25,
2182
+ cacheWritePerMillionUsd: 12.5
2183
+ }
2184
+ },
2168
2185
  // ─── OpenAI ───────────────────────────────────────────────────────────────
2169
2186
  // OpenAI was absent from the OpenRouter list entirely — not a curation
2170
2187
  // choice, a gap: the native `openai` provider carried gpt-5 while anyone
@@ -2217,6 +2234,107 @@ var init_model_catalog = __esm({
2217
2234
  cacheWritePerMillionUsd: 2.5
2218
2235
  }
2219
2236
  },
2237
+ // The rest of the 5.6 series and GPT-6 Astra, read off OpenRouter's
2238
+ // /api/v1/models on 2026-09-22 — including its `reasoning` object
2239
+ // ({mandatory, default_enabled, supported_efforts}), which is what the
2240
+ // control below follows. Sol, Sol Pro and Terra: mandatory:false,
2241
+ // supported_efforts max/xhigh/high/medium/low/none → the Luna posture
2242
+ // (four levels, Off offered). Astra and Astra Pro: mandatory:true, no
2243
+ // 'none' → the same four levels with Off hidden. Prices are the
2244
+ // STANDARD OpenAI service tier, the one the list endpoint reports; the
2245
+ // endpoints list also carries a flex tier at half and a priority tier at
2246
+ // double, and an override above 272K prompt tokens — the flat catalogue
2247
+ // price is the standard tier, as for Luna and Terra Pro above. Upstream
2248
+ // copy: Sol is the 5.6 flagship, Terra the balanced tier between Sol and
2249
+ // Luna, Astra "OpenAI's flagship model for demanding end-to-end work".
2250
+ {
2251
+ modelId: "openai/gpt-5.6-terra",
2252
+ label: "GPT-5.6 Terra",
2253
+ capabilities: {
2254
+ tools: true,
2255
+ forcedToolChoice: true,
2256
+ reasoningControl: { kind: "effort", levels: ["low", "medium", "high", "max"] }
2257
+ },
2258
+ contextWindow: 105e4,
2259
+ pricing: {
2260
+ inputPerMillionUsd: 2,
2261
+ outputPerMillionUsd: 12,
2262
+ cacheReadPerMillionUsd: 0.2,
2263
+ cacheWritePerMillionUsd: 2.5
2264
+ }
2265
+ },
2266
+ {
2267
+ modelId: "openai/gpt-5.6-sol",
2268
+ label: "GPT-5.6 Sol",
2269
+ capabilities: {
2270
+ tools: true,
2271
+ forcedToolChoice: true,
2272
+ reasoningControl: { kind: "effort", levels: ["low", "medium", "high", "max"] }
2273
+ },
2274
+ contextWindow: 105e4,
2275
+ pricing: {
2276
+ inputPerMillionUsd: 2,
2277
+ outputPerMillionUsd: 10,
2278
+ cacheReadPerMillionUsd: 0.2,
2279
+ cacheWritePerMillionUsd: 2.5
2280
+ }
2281
+ },
2282
+ {
2283
+ modelId: "openai/gpt-5.6-sol-pro",
2284
+ label: "GPT-5.6 Sol Pro",
2285
+ capabilities: {
2286
+ tools: true,
2287
+ forcedToolChoice: true,
2288
+ reasoningControl: { kind: "effort", levels: ["low", "medium", "high", "max"] }
2289
+ },
2290
+ contextWindow: 105e4,
2291
+ pricing: {
2292
+ inputPerMillionUsd: 2,
2293
+ outputPerMillionUsd: 10,
2294
+ cacheReadPerMillionUsd: 0.2,
2295
+ cacheWritePerMillionUsd: 2.5
2296
+ }
2297
+ },
2298
+ {
2299
+ modelId: "openai/gpt-6-astra",
2300
+ label: "GPT-6 Astra",
2301
+ capabilities: {
2302
+ tools: true,
2303
+ forcedToolChoice: true,
2304
+ reasoningControl: {
2305
+ kind: "effort",
2306
+ levels: ["low", "medium", "high", "max"],
2307
+ mandatory: true
2308
+ }
2309
+ },
2310
+ contextWindow: 105e4,
2311
+ pricing: {
2312
+ inputPerMillionUsd: 10,
2313
+ outputPerMillionUsd: 50,
2314
+ cacheReadPerMillionUsd: 1,
2315
+ cacheWritePerMillionUsd: 12.5
2316
+ }
2317
+ },
2318
+ {
2319
+ modelId: "openai/gpt-6-astra-pro",
2320
+ label: "GPT-6 Astra Pro",
2321
+ capabilities: {
2322
+ tools: true,
2323
+ forcedToolChoice: true,
2324
+ reasoningControl: {
2325
+ kind: "effort",
2326
+ levels: ["low", "medium", "high", "max"],
2327
+ mandatory: true
2328
+ }
2329
+ },
2330
+ contextWindow: 105e4,
2331
+ pricing: {
2332
+ inputPerMillionUsd: 10,
2333
+ outputPerMillionUsd: 50,
2334
+ cacheReadPerMillionUsd: 1,
2335
+ cacheWritePerMillionUsd: 12.5
2336
+ }
2337
+ },
2220
2338
  // Anthropic — reasoningControl WITHOUT the `reasoning` flag, on purpose:
2221
2339
  // the flag would flip openrouter.ts's always-on default injection; here
2222
2340
  // thinking is engaged only when the agent explicitly sets an effort.
@@ -2253,17 +2371,6 @@ var init_model_catalog = __esm({
2253
2371
  cacheWritePerMillionUsd: 6.25
2254
2372
  }
2255
2373
  },
2256
- {
2257
- modelId: "anthropic/claude-opus-4.7-fast",
2258
- label: "Claude Opus 4.7 (fast)",
2259
- capabilities: {
2260
- tools: true,
2261
- forcedToolChoice: true,
2262
- reasoningControl: { kind: "effort", levels: ["low", "medium", "high", "max"] }
2263
- },
2264
- contextWindow: 1e6,
2265
- pricing: { inputPerMillionUsd: 30, outputPerMillionUsd: 150 }
2266
- },
2267
2374
  {
2268
2375
  modelId: "anthropic/claude-opus-4.8",
2269
2376
  label: "Claude Opus 4.8",
@@ -2280,17 +2387,6 @@ var init_model_catalog = __esm({
2280
2387
  cacheWritePerMillionUsd: 6.25
2281
2388
  }
2282
2389
  },
2283
- {
2284
- modelId: "anthropic/claude-opus-4.8-fast",
2285
- label: "Claude Opus 4.8 (fast)",
2286
- capabilities: {
2287
- tools: true,
2288
- forcedToolChoice: true,
2289
- reasoningControl: { kind: "effort", levels: ["low", "medium", "high", "max"] }
2290
- },
2291
- contextWindow: 1e6,
2292
- pricing: { inputPerMillionUsd: 10, outputPerMillionUsd: 50 }
2293
- },
2294
2390
  {
2295
2391
  modelId: "anthropic/claude-sonnet-4.6",
2296
2392
  label: "Claude Sonnet 4.6",
@@ -2381,6 +2477,58 @@ var init_model_catalog = __esm({
2381
2477
  cacheReadPerMillionUsd: 0.064902
2382
2478
  }
2383
2479
  },
2480
+ {
2481
+ // "The GA release of DeepSeek V4 Pro" (upstream copy) — the dated
2482
+ // successor of the undated alias above. Pricing (DeepSeek's own
2483
+ // endpoint), context and supported_parameters read off /api/v1/models
2484
+ // on 2026-09-22. The levels follow the list endpoint's `reasoning`
2485
+ // object: supported_efforts max/high/low, mandatory:false — so no
2486
+ // 'medium', unlike the older entries above that predate that field.
2487
+ modelId: "deepseek/deepseek-v4-pro-0813",
2488
+ label: "DeepSeek V4 Pro (0813)",
2489
+ capabilities: {
2490
+ tools: true,
2491
+ forcedToolChoice: true,
2492
+ reasoning: true,
2493
+ reasoningControl: { kind: "effort", levels: ["low", "high", "max"] }
2494
+ },
2495
+ contextWindow: 1048576,
2496
+ providerOrder: ["deepseek"],
2497
+ pricing: {
2498
+ inputPerMillionUsd: 0.66,
2499
+ outputPerMillionUsd: 1.98,
2500
+ cacheReadPerMillionUsd: 0.022
2501
+ }
2502
+ },
2503
+ {
2504
+ // The newest Flash (2026-09-10), first on DeepSeek's Causal
2505
+ // Encoder-Decoder architecture. One difference from every V4 Flash
2506
+ // above: it takes IMAGE input (input_modalities: text, image), so it is
2507
+ // in VISION_MODEL_IDS. Same reasoning caveat as its siblings; levels
2508
+ // from the list endpoint's `reasoning` object (max/high/low,
2509
+ // mandatory:false, default_enabled:true). forcedToolChoice:false —
2510
+ // DeepSeek's own endpoint (the one providerOrder prefers) reports
2511
+ // supports_tool_choice.required:false; some fallbacks (DeepInfra,
2512
+ // Wafer) report true, and the runtime floor relaxes it anyway.
2513
+ // 'max' → OpenRouter 'xhigh' and Auto → 'medium' are not in this
2514
+ // model's supported_efforts; OpenRouter documents that it "will map
2515
+ // your requested effort to the nearest supported level".
2516
+ modelId: "deepseek/deepseek-v4.1-flash",
2517
+ label: "DeepSeek V4.1 Flash",
2518
+ capabilities: {
2519
+ tools: true,
2520
+ forcedToolChoice: false,
2521
+ reasoning: true,
2522
+ reasoningControl: { kind: "effort", levels: ["low", "high", "max"] }
2523
+ },
2524
+ contextWindow: 1048576,
2525
+ providerOrder: ["deepseek"],
2526
+ pricing: {
2527
+ inputPerMillionUsd: 0.15,
2528
+ outputPerMillionUsd: 0.6,
2529
+ cacheReadPerMillionUsd: 3e-3
2530
+ }
2531
+ },
2384
2532
  // Google — all three are thinking models on OpenRouter (supported_parameters
2385
2533
  // includes "reasoning", verified via openrouter.ai/google/… 2026-07-12).
2386
2534
  // reasoning:true makes the OpenRouter provider enable reasoning + round-trip
@@ -2632,6 +2780,93 @@ var init_model_catalog = __esm({
2632
2780
  cacheReadPerMillionUsd: 0.015
2633
2781
  }
2634
2782
  },
2783
+ {
2784
+ // "The high-speed variant of GLM-5.3-Flash ... up to 200 tokens/s"
2785
+ // (upstream copy, 2026-09-18). Same model family as Flash: multimodal
2786
+ // (text, image, video → VISION_MODEL_IDS), forcedToolChoice:false
2787
+ // (supports_tool_choice.required:false on its endpoint). The control
2788
+ // follows the list endpoint's `reasoning` object, read 2026-09-22:
2789
+ // mandatory:true, supported_efforts max/high/low, default max — the
2790
+ // full 5.3's posture, and the same object upstream now reports for
2791
+ // Flash too (the Flash entry above predates that field). It differs
2792
+ // from Flash on price (~5x) and context (1.05M, not 1.31M).
2793
+ modelId: "z-ai/glm-5.3-flashx",
2794
+ label: "GLM 5.3 FlashX",
2795
+ capabilities: {
2796
+ tools: true,
2797
+ forcedToolChoice: false,
2798
+ reasoning: true,
2799
+ reasoningControl: {
2800
+ kind: "effort",
2801
+ levels: ["low", "high", "max"],
2802
+ mandatory: true
2803
+ }
2804
+ },
2805
+ contextWindow: 1048576,
2806
+ pricing: {
2807
+ inputPerMillionUsd: 0.37,
2808
+ outputPerMillionUsd: 1.25,
2809
+ cacheReadPerMillionUsd: 0.075
2810
+ }
2811
+ },
2812
+ // Xiaomi MiMo-V2.6 — the three 2.6 models OpenRouter serves (2026-09-21),
2813
+ // all read off /api/v1/models and /models/<id>/endpoints on 2026-09-22:
2814
+ // 1.05M context, 131K max output, input_modalities text+image+video+audio
2815
+ // (→ VISION_MODEL_IDS), supported_parameters tools, tool_choice,
2816
+ // reasoning, include_reasoning — and NO reasoning_effort. The list
2817
+ // endpoint's `reasoning` object says only {mandatory:false}: no
2818
+ // supported_efforts, so thinking can be switched on or off and nothing
2819
+ // else — kind 'onoff', not a made-up scale. No always-on `reasoning`
2820
+ // flag: Auto keeps the provider's default. forcedToolChoice:true —
2821
+ // every endpoint reports supports_tool_choice.required:true.
2822
+ // Upstream copy: Flash = 309B MoE / 15B active; Pro = the >1T flagship;
2823
+ // Pro-UltraSpeed = the same Pro checkpoint "roughly 10x" faster, 10x the
2824
+ // price.
2825
+ {
2826
+ modelId: "xiaomi/mimo-v2.6-flash",
2827
+ label: "MiMo V2.6 Flash",
2828
+ capabilities: {
2829
+ tools: true,
2830
+ forcedToolChoice: true,
2831
+ reasoningControl: { kind: "onoff" }
2832
+ },
2833
+ contextWindow: 1048576,
2834
+ pricing: {
2835
+ inputPerMillionUsd: 0.14,
2836
+ outputPerMillionUsd: 0.28,
2837
+ cacheReadPerMillionUsd: 28e-4
2838
+ }
2839
+ },
2840
+ {
2841
+ modelId: "xiaomi/mimo-v2.6-pro",
2842
+ label: "MiMo V2.6 Pro",
2843
+ capabilities: {
2844
+ tools: true,
2845
+ forcedToolChoice: true,
2846
+ reasoningControl: { kind: "onoff" }
2847
+ },
2848
+ contextWindow: 1048576,
2849
+ pricing: {
2850
+ inputPerMillionUsd: 0.435,
2851
+ outputPerMillionUsd: 0.87,
2852
+ cacheReadPerMillionUsd: 36e-4
2853
+ }
2854
+ },
2855
+ {
2856
+ modelId: "xiaomi/mimo-v2.6-pro-ultraspeed",
2857
+ label: "MiMo V2.6 Pro UltraSpeed",
2858
+ capabilities: {
2859
+ tools: true,
2860
+ forcedToolChoice: true,
2861
+ reasoningControl: { kind: "onoff" }
2862
+ },
2863
+ contextWindow: 1048576,
2864
+ pricing: {
2865
+ inputPerMillionUsd: 4.35,
2866
+ outputPerMillionUsd: 8.7,
2867
+ cacheReadPerMillionUsd: 0.036
2868
+ }
2869
+ },
2635
2870
  // Moonshot (Kimi)
2636
2871
  {
2637
2872
  modelId: "moonshotai/kimi-k2.6",
@@ -2710,6 +2945,56 @@ var init_model_catalog = __esm({
2710
2945
  cacheReadPerMillionUsd: 0.3
2711
2946
  }
2712
2947
  },
2948
+ // Grok 4.6 (2026-08-12) and 4.7 (2026-09-21, "succeeding Grok 4.6" per
2949
+ // upstream copy): same 500K context, same text+image+file input
2950
+ // (→ VISION_MODEL_IDS), same supported_parameters as 4.5 (tools,
2951
+ // tool_choice, reasoning, reasoning_effort), read off /api/v1/models and
2952
+ // /models/<id>/endpoints on 2026-09-22. The control follows the list
2953
+ // endpoint's `reasoning` object: mandatory:true (no Off), and — unlike
2954
+ // 4.5, whose object stops at high — supported_efforts xhigh/high/medium/
2955
+ // low, so 'max' (→ xhigh) is offered. Pricing: 4.6 = 4.5; 4.7 is 20%
2956
+ // cheaper. Both double above 200K prompt tokens (an override the flat
2957
+ // price does not carry, same as 4.5).
2958
+ {
2959
+ modelId: "x-ai/grok-4.6",
2960
+ label: "Grok 4.6",
2961
+ capabilities: {
2962
+ tools: true,
2963
+ forcedToolChoice: true,
2964
+ reasoning: true,
2965
+ reasoningControl: {
2966
+ kind: "effort",
2967
+ levels: ["low", "medium", "high", "max"],
2968
+ mandatory: true
2969
+ }
2970
+ },
2971
+ contextWindow: 5e5,
2972
+ pricing: {
2973
+ inputPerMillionUsd: 2,
2974
+ outputPerMillionUsd: 6,
2975
+ cacheReadPerMillionUsd: 0.5
2976
+ }
2977
+ },
2978
+ {
2979
+ modelId: "x-ai/grok-4.7",
2980
+ label: "Grok 4.7",
2981
+ capabilities: {
2982
+ tools: true,
2983
+ forcedToolChoice: true,
2984
+ reasoning: true,
2985
+ reasoningControl: {
2986
+ kind: "effort",
2987
+ levels: ["low", "medium", "high", "max"],
2988
+ mandatory: true
2989
+ }
2990
+ },
2991
+ contextWindow: 5e5,
2992
+ pricing: {
2993
+ inputPerMillionUsd: 1.6,
2994
+ outputPerMillionUsd: 4.8,
2995
+ cacheReadPerMillionUsd: 0.4
2996
+ }
2997
+ },
2713
2998
  // Qwen — both verified via OpenRouter /api/v1/models (2026-07-20): 1M
2714
2999
  // context, tools + tool_choice + reasoning params (no native
2715
3000
  // reasoning_effort — OpenRouter's unified param drives the hybrid
@@ -2792,13 +3077,12 @@ var init_model_catalog = __esm({
2792
3077
  VISION_MODEL_IDS = /* @__PURE__ */ new Set([
2793
3078
  // OpenRouter (verified via /api/v1/models)
2794
3079
  "anthropic/claude-fable-5",
3080
+ // input_modalities ["text","image","file"] on /api/v1/models, 2026-09-22.
3081
+ "anthropic/claude-fable-5.1",
2795
3082
  "anthropic/claude-haiku-4.5",
2796
3083
  "anthropic/claude-opus-4.7",
2797
- "anthropic/claude-opus-4.7-fast",
2798
3084
  "anthropic/claude-opus-4.8",
2799
- "anthropic/claude-opus-4.8-fast",
2800
3085
  "anthropic/claude-opus-5",
2801
- "anthropic/claude-opus-5-fast",
2802
3086
  "anthropic/claude-sonnet-4.6",
2803
3087
  "anthropic/claude-sonnet-5",
2804
3088
  "google/gemini-3.1-flash-lite-preview",
@@ -2814,14 +3098,35 @@ var init_model_catalog = __esm({
2814
3098
  "openai/gpt-5.6-luna",
2815
3099
  "openai/gpt-5.6-luna-pro",
2816
3100
  "openai/gpt-5.6-terra-pro",
3101
+ // The rest of the 5.6 series and GPT-6 Astra: input_modalities
3102
+ // ["file","image","text"] on /api/v1/models, 2026-09-22.
3103
+ "openai/gpt-5.6-terra",
3104
+ "openai/gpt-5.6-sol",
3105
+ "openai/gpt-5.6-sol-pro",
3106
+ "openai/gpt-6-astra",
3107
+ "openai/gpt-6-astra-pro",
3108
+ // deepseek/deepseek-v4.1-flash reports ["text","image"] (2026-09-22) — the
3109
+ // first V4 Flash that does; v4-flash, v4-flash-0731 and both V4 Pro are
3110
+ // text-only per the same source and deliberately NOT in this set.
3111
+ "deepseek/deepseek-v4.1-flash",
2817
3112
  "qwen/qwen3.8-max",
2818
3113
  // Verified via OpenRouter /api/v1/models input_modalities on 2026-08-28:
2819
3114
  // z-ai/glm-5.3-flash reports ["text","image","video"]. The full z-ai/glm-5.3
2820
3115
  // reports ["text"] only and is deliberately NOT in this set.
2821
3116
  "z-ai/glm-5.3-flash",
3117
+ // z-ai/glm-5.3-flashx reports the same ["text","image","video"] (2026-09-22).
3118
+ "z-ai/glm-5.3-flashx",
3119
+ // Xiaomi MiMo-V2.6: all three report ["text","image","video","audio"]
3120
+ // (2026-09-22).
3121
+ "xiaomi/mimo-v2.6-flash",
3122
+ "xiaomi/mimo-v2.6-pro",
3123
+ "xiaomi/mimo-v2.6-pro-ultraspeed",
2822
3124
  // Verified via OpenRouter /api/v1/models input_modalities (2026-07-20).
2823
3125
  // qwen/qwen3.7-max is deliberately absent — text-only per the same source.
2824
3126
  "x-ai/grok-4.5",
3127
+ // 4.6 and 4.7 report the same ["text","image","file"] (2026-09-22).
3128
+ "x-ai/grok-4.6",
3129
+ "x-ai/grok-4.7",
2825
3130
  "qwen/qwen3.7-plus",
2826
3131
  // Native-provider forms
2827
3132
  "claude-fable-5",
@@ -4300,10 +4605,10 @@ var init_entities = __esm({
4300
4605
  updatedAt: timestamp2("updated_at", { withTimezone: true }).defaultNow(),
4301
4606
  lastCuratorRunAt: timestamp2("last_curator_run_at", { withTimezone: true }),
4302
4607
  reflectionEnabled: boolean2("reflection_enabled").notNull().default(false),
4303
- // Decoupled from reflection_enabled (which gates the skill-learning loop,
4304
- // opt-in). Gates the memory curator (Phase 2 LLM pass) — ON by default so
4305
- // memory curation runs even for entities that never opted into reflection.
4306
- memoryCurationEnabled: boolean2("memory_curation_enabled").notNull().default(true),
4608
+ // `memory_curation_enabled` lived here from 0.7.0 to migration 0122 (#411):
4609
+ // a per-workspace gate on the memory curator that no screen ever exposed.
4610
+ // Memory curation is now gated by the runner's MEMORY_CURATION_ENABLED
4611
+ // kill-switch only; "do not touch this fact" is the pin on the fact.
4307
4612
  // Controls whether agent-authored skills are auto-assigned to the authoring
4308
4613
  // agent ('auto') or queued for the entity owner to approve ('approval').
4309
4614
  skillAssignmentMode: text3("skill_assignment_mode").notNull().default("approval").$type(),
@@ -266894,12 +267199,12 @@ var envSchema = z.object({
266894
267199
  // (Phase 2 LLM pass) specifically — decoupled from the skill-learning loop:
266895
267200
  // MEMORY_CURATION_ENABLED='false' → global kill: disables memory curation
266896
267201
  // for every entity.
266897
- // MEMORY_CURATION_ENABLED='' → per-entity decides (production default
266898
- // (unset) when the var is absent). Since
266899
- // entities.memory_curation_enabled
266900
- // defaults TRUE, memory curation runs
266901
- // out of the box — unlike reflection.
266902
- // MEMORY_CURATION_ENABLED='true' → per-entity decides (same as unset).
267202
+ // MEMORY_CURATION_ENABLED='' → memory curation runs for every entity
267203
+ // (unset) (production default when the var is
267204
+ // absent) — out of the box, unlike
267205
+ // reflection. No per-entity gate any
267206
+ // more (#411).
267207
+ // MEMORY_CURATION_ENABLED='true' → same as unset.
266903
267208
  MEMORY_CURATION_ENABLED: z.string().default(""),
266904
267209
  // Optional. When set, the reflection + curator passes use THIS model id instead of
266905
267210
  // the agent's model — resolved against the agent's existing LLM key (ideal for an
@@ -270852,8 +271157,39 @@ import { existsSync as existsSync3 } from "node:fs";
270852
271157
  import { join as join3 } from "node:path";
270853
271158
  import { promisify } from "node:util";
270854
271159
 
271160
+ // ../../packages/shared/src/git-binary.ts
271161
+ import { stat } from "node:fs/promises";
271162
+ import { delimiter as PATH_DELIMITER } from "node:path";
271163
+ var EXTENSIONS_WINDOWS = [".exe", ".com"];
271164
+ function enBarresObliques(chemin) {
271165
+ return chemin.replace(/\\/g, "/");
271166
+ }
271167
+ async function estFichier(chemin) {
271168
+ try {
271169
+ return (await stat(chemin)).isFile();
271170
+ } catch {
271171
+ return false;
271172
+ }
271173
+ }
271174
+ var gitBinaire = null;
271175
+ async function resolveGitBinary() {
271176
+ gitBinaire ??= (async () => {
271177
+ const chemins = (process.env["PATH"] ?? "").split(PATH_DELIMITER).filter((d) => d !== "");
271178
+ const windows = process.platform === "win32";
271179
+ for (const dossier of chemins) {
271180
+ const base = `${enBarresObliques(dossier)}/git`;
271181
+ for (const ext of windows ? EXTENSIONS_WINDOWS : [""]) {
271182
+ if (await estFichier(base + ext)) return base + ext;
271183
+ }
271184
+ }
271185
+ console.warn("[git] GIT_NOT_ON_PATH");
271186
+ return null;
271187
+ })();
271188
+ return gitBinaire;
271189
+ }
271190
+
270855
271191
  // ../../packages/checkpoints/src/failure.ts
270856
- import { readdir as readdir2, stat } from "node:fs/promises";
271192
+ import { readdir as readdir2, stat as stat2 } from "node:fs/promises";
270857
271193
  import { basename, join as join2 } from "node:path";
270858
271194
  function checkpointFailureCode(cause, operation) {
270859
271195
  if (cause === "git_missing") return "git_missing";
@@ -270912,7 +271248,7 @@ async function measureWorkspace(workspace, limits = {}) {
270912
271248
  }
270913
271249
  files++;
270914
271250
  try {
270915
- bytes += (await stat(join2(dir, entry.name))).size;
271251
+ bytes += (await stat2(join2(dir, entry.name))).size;
270916
271252
  } catch {
270917
271253
  }
270918
271254
  }
@@ -271061,7 +271397,21 @@ function isTimeoutError(err) {
271061
271397
  const e2 = err;
271062
271398
  return e2.killed === true || e2.code === "ETIMEDOUT";
271063
271399
  }
271400
+ var GitBinaryMissingError = class extends Error {
271401
+ constructor() {
271402
+ super(
271403
+ "git is not on PATH: no checkpoint can be taken or read. Install git, or make it reachable from the process PATH."
271404
+ );
271405
+ this.name = "GitBinaryMissingError";
271406
+ }
271407
+ };
271408
+ async function gitBinary() {
271409
+ const binaire = await resolveGitBinary();
271410
+ if (binaire === null) throw new GitBinaryMissingError();
271411
+ return binaire;
271412
+ }
271064
271413
  function isGitMissingError(err) {
271414
+ if (err instanceof GitBinaryMissingError) return true;
271065
271415
  if (typeof err !== "object" || err === null) return false;
271066
271416
  const e2 = err;
271067
271417
  return e2.code === "ENOENT" && typeof e2.syscall === "string" && e2.syscall.startsWith("spawn");
@@ -271137,7 +271487,7 @@ function gitEnv(store, workspace, indexFile) {
271137
271487
  };
271138
271488
  }
271139
271489
  async function git(store, workspace, args, indexFile, timeoutMs = storeTimeoutMs()) {
271140
- const { stdout } = await run("git", args, {
271490
+ const { stdout } = await run(await gitBinary(), args, {
271141
271491
  timeout: timeoutMs,
271142
271492
  windowsHide: true,
271143
271493
  env: gitEnv(store, workspace, indexFile)
@@ -271145,7 +271495,7 @@ async function git(store, workspace, args, indexFile, timeoutMs = storeTimeoutMs
271145
271495
  return stdout.trim();
271146
271496
  }
271147
271497
  async function gitRaw(store, workspace, args, indexFile) {
271148
- const { stdout } = await run("git", args, {
271498
+ const { stdout } = await run(await gitBinary(), args, {
271149
271499
  timeout: storeTimeoutMs(),
271150
271500
  windowsHide: true,
271151
271501
  maxBuffer: 8 * 1024 * 1024,
@@ -271159,9 +271509,10 @@ function cutAtUtf8Boundary(buf, max2) {
271159
271509
  while (end > 0 && (buf[end] & 192) === 128) end--;
271160
271510
  return buf.subarray(0, end);
271161
271511
  }
271162
- function gitRawCapped(store, workspace, args, maxBytes, indexFile) {
271512
+ async function gitRawCapped(store, workspace, args, maxBytes, indexFile) {
271513
+ const binaire = await gitBinary();
271163
271514
  return new Promise((resolve3, reject) => {
271164
- const child = spawn("git", args, {
271515
+ const child = spawn(binaire, args, {
271165
271516
  windowsHide: true,
271166
271517
  env: gitEnv(store, workspace, indexFile)
271167
271518
  });
@@ -271215,7 +271566,7 @@ async function ensureStore(store) {
271215
271566
  await writeFile(join3(store, "gitconfig"), "", { flag: "a" });
271216
271567
  if (!existsSync3(join3(gitDir, "HEAD"))) {
271217
271568
  await mkdir(gitDir, { recursive: true });
271218
- await run("git", ["init", "--bare", "--quiet", gitDir], {
271569
+ await run(await gitBinary(), ["init", "--bare", "--quiet", gitDir], {
271219
271570
  timeout: GIT_TIMEOUT_MS,
271220
271571
  windowsHide: true
271221
271572
  });
@@ -271363,7 +271714,7 @@ async function markDeliverablesProduced(db, jobId, deliverables, observedKeys) {
271363
271714
  }
271364
271715
 
271365
271716
  // ../../packages/tools/src/verification/harness.ts
271366
- import { stat as stat2 } from "node:fs/promises";
271717
+ import { stat as stat3 } from "node:fs/promises";
271367
271718
  init_src();
271368
271719
  async function lignesDeHarnaisDejaLa(db, jobId) {
271369
271720
  if (!jobId) return /* @__PURE__ */ new Set();
@@ -271406,7 +271757,7 @@ async function constatedHarnessWrites(input) {
271406
271757
  vus.add(path4);
271407
271758
  let present;
271408
271759
  try {
271409
- present = (await stat2(path4)).isFile();
271760
+ present = (await stat3(path4)).isFile();
271410
271761
  } catch {
271411
271762
  present = false;
271412
271763
  }
@@ -271426,7 +271777,7 @@ async function constatedHarnessWrites(input) {
271426
271777
  // ../../packages/tools/src/verification/observed.ts
271427
271778
  init_src();
271428
271779
  import { createHash as createHash3 } from "node:crypto";
271429
- import { readFile, stat as stat3 } from "node:fs/promises";
271780
+ import { readFile, stat as stat4 } from "node:fs/promises";
271430
271781
  var ABSENT = { kind: "absent" };
271431
271782
  function estAbsence(error) {
271432
271783
  const code = error?.code;
@@ -271435,7 +271786,7 @@ function estAbsence(error) {
271435
271786
  async function fingerprint(path4) {
271436
271787
  let size;
271437
271788
  try {
271438
- const s = await stat3(path4, { bigint: true });
271789
+ const s = await stat4(path4, { bigint: true });
271439
271790
  if (!s.isFile()) return ABSENT;
271440
271791
  size = s.size;
271441
271792
  } catch (error) {
@@ -271516,39 +271867,6 @@ init_src();
271516
271867
  import { execFile as execFile2 } from "node:child_process";
271517
271868
  import { realpath } from "node:fs/promises";
271518
271869
  import { promisify as promisify2 } from "node:util";
271519
-
271520
- // ../../packages/shared/src/git-binary.ts
271521
- import { stat as stat4 } from "node:fs/promises";
271522
- import { delimiter as PATH_DELIMITER } from "node:path";
271523
- var EXTENSIONS_WINDOWS = [".exe", ".com"];
271524
- function enBarresObliques(chemin) {
271525
- return chemin.replace(/\\/g, "/");
271526
- }
271527
- async function estFichier(chemin) {
271528
- try {
271529
- return (await stat4(chemin)).isFile();
271530
- } catch {
271531
- return false;
271532
- }
271533
- }
271534
- var gitBinaire = null;
271535
- async function resolveGitBinary() {
271536
- gitBinaire ??= (async () => {
271537
- const chemins = (process.env["PATH"] ?? "").split(PATH_DELIMITER).filter((d) => d !== "");
271538
- const windows = process.platform === "win32";
271539
- for (const dossier of chemins) {
271540
- const base = `${enBarresObliques(dossier)}/git`;
271541
- for (const ext of windows ? EXTENSIONS_WINDOWS : [""]) {
271542
- if (await estFichier(base + ext)) return base + ext;
271543
- }
271544
- }
271545
- console.warn("[git] GIT_NOT_ON_PATH");
271546
- return null;
271547
- })();
271548
- return gitBinaire;
271549
- }
271550
-
271551
- // ../../packages/tools/src/verification/git-constat.ts
271552
271870
  var run2 = promisify2(execFile2);
271553
271871
  var GIT_TIMEOUT_MS2 = 5e3;
271554
271872
  var MAX_STATUS_ENTRIES = 1e3;
@@ -274154,6 +274472,7 @@ init_src();
274154
274472
  function classifyWrittenFile(input) {
274155
274473
  const path4 = normalizePath(input.absPath);
274156
274474
  const dir = path4.replace(/\/[^/]*$/, "");
274475
+ const name = path4.slice(dir.length + 1);
274157
274476
  for (const declared of input.declaredCodeProjectPaths) {
274158
274477
  const root = normalizePath(declared);
274159
274478
  if (root !== "" && isWithinRoot(dir, root)) return "code_project";
@@ -274163,7 +274482,11 @@ function classifyWrittenFile(input) {
274163
274482
  workspaceRoots: input.workspaceRoots,
274164
274483
  hasMarker: input.hasMarker
274165
274484
  });
274166
- if (project !== void 0 && input.hasMarker(project.path)) return "code_project";
274485
+ if (project !== void 0) {
274486
+ if (input.hasMarker(project.path)) return "code_project";
274487
+ const aLaRacine = project.key === projectKey(dir);
274488
+ if (aLaRacine && name !== ".git" && PROJECT_MARKERS.includes(name)) return "code_project";
274489
+ }
274167
274490
  return "document";
274168
274491
  }
274169
274492
  async function deliverableTypeForWrittenFile(ctx, absPath) {
@@ -489651,6 +489974,28 @@ async function fillResultFromChildrenIfEmpty(db, jobId) {
489651
489974
  if (!compiled) return;
489652
489975
  await db.update(agentJobs).set({ result: compiled, resultKind: "relay", updatedAt: /* @__PURE__ */ new Date() }).where(and8(eq10(agentJobs.id, jobId), or4(isNull2(agentJobs.result), eq10(agentJobs.result, ""))));
489653
489976
  }
489977
+ function messageText(content3) {
489978
+ if (typeof content3 === "string") return content3;
489979
+ if (!Array.isArray(content3)) return "";
489980
+ const parts = [];
489981
+ for (const p of content3) {
489982
+ const part = p;
489983
+ if (part && part.type === "text" && typeof part.text === "string") parts.push(part.text);
489984
+ }
489985
+ return parts.join("");
489986
+ }
489987
+ function findTaskBoundary(messages, task) {
489988
+ if (task.trim() === "") return -1;
489989
+ for (let i = messages.length - 1; i >= 0; i--) {
489990
+ const m = messages[i];
489991
+ if (m && m.role === "user" && messageText(m.content) === task) return i;
489992
+ }
489993
+ return -1;
489994
+ }
489995
+ function currentTurnMessages(messages, task) {
489996
+ const i = findTaskBoundary(messages, task);
489997
+ return i === -1 ? messages : messages.slice(i);
489998
+ }
489654
489999
  function lastAssistantText(messages) {
489655
490000
  if (!Array.isArray(messages)) return "";
489656
490001
  for (let i = messages.length - 1; i >= 0; i--) {
@@ -489671,9 +490016,16 @@ function lastAssistantText(messages) {
489671
490016
  return "";
489672
490017
  }
489673
490018
  async function fillResultFromFinalTextIfEmpty(db, jobId, messages) {
489674
- const [row] = await db.select({ result: agentJobs.result }).from(agentJobs).where(eq10(agentJobs.id, jobId)).limit(1);
490019
+ const [row] = await db.select({ result: agentJobs.result, task: agentJobs.task }).from(agentJobs).where(eq10(agentJobs.id, jobId)).limit(1);
489675
490020
  if ((row?.result ?? "").trim().length > 0) return;
489676
- const text36 = lastAssistantText(messages);
490021
+ if (Array.isArray(messages) && findTaskBoundary(messages, row?.task ?? "") === -1) {
490022
+ console.warn(
490023
+ `[job ${jobId}] task not found in the transcript \u2014 the result fallback reads the whole transcript, replayed history included`
490024
+ );
490025
+ }
490026
+ const text36 = lastAssistantText(
490027
+ Array.isArray(messages) ? currentTurnMessages(messages, row?.task ?? "") : messages
490028
+ );
489677
490029
  if (!text36) return;
489678
490030
  await db.update(agentJobs).set({ result: text36, resultKind: "prose", updatedAt: /* @__PURE__ */ new Date() }).where(and8(eq10(agentJobs.id, jobId), or4(isNull2(agentJobs.result), eq10(agentJobs.result, ""))));
489679
490031
  }
@@ -504069,8 +504421,14 @@ import { promisify as promisify7 } from "node:util";
504069
504421
  var run3 = promisify7(execFile3);
504070
504422
  var GIT_TIMEOUT_MS3 = 5e3;
504071
504423
  async function git3(cwd, args) {
504424
+ const binaire = await resolveGitBinary();
504425
+ if (binaire === null) return null;
504072
504426
  try {
504073
- const { stdout } = await run3("git", args, { cwd, timeout: GIT_TIMEOUT_MS3, windowsHide: true });
504427
+ const { stdout } = await run3(binaire, args, {
504428
+ cwd,
504429
+ timeout: GIT_TIMEOUT_MS3,
504430
+ windowsHide: true
504431
+ });
504074
504432
  return stdout.trim();
504075
504433
  } catch {
504076
504434
  return null;
@@ -509018,7 +509376,10 @@ ${notice}` : notice;
509018
509376
  }
509019
509377
  }
509020
509378
  let lastAssistantTextSeen = "";
509021
- for (const m of messages) {
509379
+ if (findTaskBoundary(messages, job.task) === -1) {
509380
+ trace("current_turn_boundary_missing", { messages: messages.length });
509381
+ }
509382
+ for (const m of currentTurnMessages(messages, job.task)) {
509022
509383
  if (!m || m.role !== "assistant") continue;
509023
509384
  const c = m.content;
509024
509385
  if (typeof c === "string") {
@@ -512093,8 +512454,8 @@ var SAFE_LIFECYCLE_DEFAULTS = {
512093
512454
  REFLECTION_ENABLED: "false",
512094
512455
  // Conservative fallback for environments without DATABASE_URL (test envs) —
512095
512456
  // mirrors REFLECTION_ENABLED's safe default. The REAL production default
512096
- // (per-entity decides, ON since entities.memory_curation_enabled defaults
512097
- // true) comes from the zod schema in env.ts, not from this fallback.
512457
+ // (ON for every entity — no per-entity gate since #411) comes from the zod
512458
+ // schema in env.ts, not from this fallback.
512098
512459
  MEMORY_CURATION_ENABLED: "false",
512099
512460
  REFLECTION_MODEL: void 0
512100
512461
  };
@@ -512145,7 +512506,7 @@ async function runCuratorTick(db, _deps, runnerEnv) {
512145
512506
  }
512146
512507
  const memorySet = /* @__PURE__ */ new Set();
512147
512508
  if (e2.MEMORY_CURATION_ENABLED !== "false") {
512148
- const memoryCandidates = await db.select({ entityId: agentMemory.entityId }).from(agentMemory).innerJoin(entities, eq10(entities.id, agentMemory.entityId)).where(and8(eq10(agentMemory.archived, false), eq10(entities.memoryCurationEnabled, true))).groupBy(agentMemory.entityId).having(sql30`count(${agentMemory.id}) >= ${e2.CURATOR_MEMORY_MIN}`);
512509
+ const memoryCandidates = await db.select({ entityId: agentMemory.entityId }).from(agentMemory).where(eq10(agentMemory.archived, false)).groupBy(agentMemory.entityId).having(sql30`count(${agentMemory.id}) >= ${e2.CURATOR_MEMORY_MIN}`);
512149
512510
  for (const c of memoryCandidates) if (c.entityId) memorySet.add(c.entityId);
512150
512511
  }
512151
512512
  if (skillSet.size === 0 && memorySet.size === 0) {