nolo-cli 0.1.40 → 0.1.42

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 (482) hide show
  1. package/README.md +27 -12
  2. package/agent-runtime/agentThread.ts +222 -0
  3. package/agent-runtime/agentThreadAdmission.ts +74 -0
  4. package/agent-runtime/dialogWritePlan.ts +42 -0
  5. package/agent-runtime/hostAdapter.ts +1 -0
  6. package/agent-runtime/hybridRecordStore.ts +5 -3
  7. package/agent-runtime/index.ts +43 -0
  8. package/agent-runtime/localLoop.ts +31 -2
  9. package/agent-runtime/localToolPolicy.ts +1 -0
  10. package/agent-runtime/localWorkspaceTools.ts +1258 -78
  11. package/agent-runtime/noloWorkspaceTools.ts +20 -1
  12. package/agent-runtime/runtimeToolPolicy.ts +1 -5
  13. package/agent-runtime/runtimeToolSurface.ts +1 -0
  14. package/agentAliases.ts +29 -9
  15. package/agentInternalCommandEntries.ts +11 -3
  16. package/agentMachineCommands.ts +1 -0
  17. package/agentRecordCommands.ts +2 -2
  18. package/agentRecordHelpers.ts +59 -6
  19. package/agentRunCommand.ts +84 -19
  20. package/ai/agent/_executeModel.ts +146 -0
  21. package/ai/agent/agentSlice.ts +556 -1
  22. package/ai/agent/appWorkingMemory.ts +126 -0
  23. package/ai/agent/buildEditingContext.ts +378 -0
  24. package/ai/agent/buildSystemPrompt.ts +599 -0
  25. package/ai/agent/canvasEditingContext.ts +49 -0
  26. package/ai/agent/cleanAgentMessages.ts +140 -0
  27. package/ai/agent/cliChatClient.ts +153 -0
  28. package/ai/agent/cliExecutor.ts +264 -46
  29. package/ai/agent/contextCompiler.ts +107 -0
  30. package/ai/agent/contextLayerContract.ts +44 -0
  31. package/ai/agent/createAgentSchema.ts +272 -0
  32. package/ai/agent/currentTimeContext.ts +65 -0
  33. package/ai/agent/executeToolCall.ts +58 -0
  34. package/ai/agent/fetchAgentContexts.ts +42 -0
  35. package/ai/agent/generatePrompt.ts +3 -0
  36. package/ai/agent/getFullChatContextKeys.ts +168 -0
  37. package/ai/agent/guidedCreation/capabilities.ts +84 -0
  38. package/ai/agent/guidedCreation/types.ts +38 -0
  39. package/ai/agent/isLiveAudioOnlyAgent.ts +26 -0
  40. package/ai/agent/liveAudioModel.ts +2 -0
  41. package/ai/agent/pageBuilderHandoffRules.ts +75 -0
  42. package/ai/agent/persistMessageWithFixedId.ts +37 -0
  43. package/ai/agent/planSlice.ts +259 -0
  44. package/ai/agent/referenceUtils.ts +229 -0
  45. package/ai/agent/runAgentBackground.ts +310 -0
  46. package/ai/agent/runAgentClientLoop.ts +164 -0
  47. package/ai/agent/runtimeGuidance.ts +116 -0
  48. package/ai/agent/serverOrigin.ts +7 -0
  49. package/ai/agent/startParallelAgentStreams.ts +424 -0
  50. package/ai/agent/startupProtocol.ts +53 -0
  51. package/ai/agent/streamAgentChatTurn.ts +2135 -0
  52. package/ai/agent/streamAgentChatTurnUtils.ts +923 -0
  53. package/ai/agent/toolFailureGuard.ts +99 -0
  54. package/ai/agent/types.ts +73 -0
  55. package/ai/agent/utils/imageOutput.ts +37 -0
  56. package/ai/agent/utils/publicImageAgentMode.ts +26 -0
  57. package/ai/ai.locale.ts +1165 -0
  58. package/ai/chat/accumulateToolCallChunks.ts +126 -0
  59. package/ai/chat/fetchUtils.ts +143 -0
  60. package/ai/chat/inlineImageUrlsForCustomProvider.ts +122 -0
  61. package/ai/chat/parseApiError.ts +67 -0
  62. package/ai/chat/parseMultilineSSE.ts +95 -0
  63. package/ai/chat/sendOpenAICompletionsRequest.ts +921 -0
  64. package/ai/chat/sendOpenAIResponseRequest.ts +720 -0
  65. package/ai/chat/serverProxyRetry.ts +102 -0
  66. package/ai/chat/shouldUseServerProxy.ts +18 -0
  67. package/ai/chat/streamRetry.ts +46 -0
  68. package/ai/chat/updateTotalUsage.ts +89 -0
  69. package/ai/context/buildReferenceContext.ts +437 -0
  70. package/ai/context/retention.ts +165 -0
  71. package/ai/context/tokenUtils.ts +78 -0
  72. package/ai/llm/agentCapabilities.ts +74 -0
  73. package/ai/llm/deepinfra.ts +79 -0
  74. package/ai/llm/fireworks.ts +68 -0
  75. package/ai/llm/generateRequestBody.ts +165 -0
  76. package/ai/llm/getModelContextWindow.ts +93 -0
  77. package/ai/llm/getPricing.ts +252 -0
  78. package/ai/llm/imagePricing.ts +66 -0
  79. package/ai/llm/isResponseAPIModel.ts +13 -0
  80. package/ai/llm/kimi.ts +22 -0
  81. package/ai/llm/mimo.ts +99 -0
  82. package/ai/llm/mistral.ts +21 -0
  83. package/ai/llm/models.ts +45 -0
  84. package/ai/llm/openrouterModels.ts +31 -0
  85. package/ai/llm/providers.ts +313 -0
  86. package/ai/llm/reasoningModels.ts +27 -0
  87. package/ai/llm/types.ts +82 -0
  88. package/ai/llm/usageRequestOptions.ts +59 -0
  89. package/ai/memory/policy.ts +49 -0
  90. package/ai/memory/queryShared.ts +167 -0
  91. package/ai/memory/recentRelationshipRecap.ts +251 -0
  92. package/ai/memory/remember.ts +111 -0
  93. package/ai/memory/scope.ts +74 -0
  94. package/ai/memory/store.ts +20 -0
  95. package/ai/memory/storeShared.ts +76 -0
  96. package/ai/memory/types.ts +52 -0
  97. package/ai/memory/understanding.ts +341 -0
  98. package/ai/memory/understandingGreeting.ts +264 -0
  99. package/ai/policy/personalizationDialog.ts +333 -0
  100. package/ai/policy/runtimePolicy.ts +526 -0
  101. package/ai/policy/selfUpdateFields.ts +48 -0
  102. package/ai/policy/types.ts +64 -0
  103. package/ai/skills/referenceRuntime.ts +274 -0
  104. package/ai/skills/skillDiagnostics.ts +251 -0
  105. package/ai/skills/skillDocBuilder.ts +139 -0
  106. package/ai/skills/skillSummaryMarker.ts +26 -0
  107. package/ai/token/calculatePrice.ts +576 -0
  108. package/ai/token/missingUsageEstimate.ts +42 -0
  109. package/ai/token/normalizeUsage.ts +124 -0
  110. package/ai/token/openaiImageGenerationUsage.ts +56 -0
  111. package/ai/token/prepareTokenUsageData.ts +93 -0
  112. package/ai/token/resolveBillingTarget.ts +52 -0
  113. package/ai/token/saveTokenRecord.ts +53 -0
  114. package/ai/token/types.ts +103 -0
  115. package/ai/tools/agent/agentTools.ts +214 -0
  116. package/ai/tools/agent/agentUpdateShared.ts +311 -0
  117. package/ai/tools/agent/callAgentTool.ts +139 -0
  118. package/ai/tools/agent/createAgentTool.ts +512 -0
  119. package/ai/tools/agent/createDialogTool.ts +69 -0
  120. package/ai/tools/agent/createSkillAgentTool.ts +62 -0
  121. package/ai/tools/agent/parallelBudget.ts +221 -0
  122. package/ai/tools/agent/prepareAgentDraftTool.ts +159 -0
  123. package/ai/tools/agent/presets/appBuilderPreset.ts +154 -0
  124. package/ai/tools/agent/runLlmTool.ts +96 -0
  125. package/ai/tools/agent/runStreamingAgentTool.ts +73 -0
  126. package/ai/tools/agent/skillAgentArgs.ts +106 -0
  127. package/ai/tools/agent/startAgentDialogTool.ts +54 -0
  128. package/ai/tools/agent/streamParallelAgentsTool.ts +123 -0
  129. package/ai/tools/agent/updateAgentTool.ts +96 -0
  130. package/ai/tools/agent/updateSelfTool.ts +113 -0
  131. package/ai/tools/amazonProductScraperTool.ts +86 -0
  132. package/ai/tools/apifyActorClient.ts +45 -0
  133. package/ai/tools/appEditGuard.ts +372 -0
  134. package/ai/tools/appReadSnapshot.ts +153 -0
  135. package/ai/tools/appTools.ts +1549 -0
  136. package/ai/tools/applyEditTool.ts +259 -0
  137. package/ai/tools/applyLineEditsTool.ts +315 -0
  138. package/ai/tools/browserTools/click.ts +33 -0
  139. package/ai/tools/browserTools/closeSession.ts +29 -0
  140. package/ai/tools/browserTools/common.ts +27 -0
  141. package/ai/tools/browserTools/openSession.ts +48 -0
  142. package/ai/tools/browserTools/readContent.ts +38 -0
  143. package/ai/tools/browserTools/selectOption.ts +46 -0
  144. package/ai/tools/browserTools/typeText.ts +42 -0
  145. package/ai/tools/category/createCategoryTool.ts +66 -0
  146. package/ai/tools/category/queryContentsByCategoryTool.ts +69 -0
  147. package/ai/tools/category/updateContentCategoryTool.ts +75 -0
  148. package/ai/tools/cfBrowserTools.ts +319 -0
  149. package/ai/tools/cfSpeechToTextTool.ts +49 -0
  150. package/ai/tools/checkEnvTool.ts +102 -0
  151. package/ai/tools/cloudflareCrawlTool.ts +289 -0
  152. package/ai/tools/codeSearchTool.ts +123 -0
  153. package/ai/tools/codeTools.ts +101 -0
  154. package/ai/tools/convertMarxistsBookTool.ts +103 -0
  155. package/ai/tools/createDocTool.ts +132 -0
  156. package/ai/tools/createSkillDocTool.ts +155 -0
  157. package/ai/tools/createWorkflowTool.ts +154 -0
  158. package/ai/tools/delayTool.ts +31 -0
  159. package/ai/tools/deleteSpacesTool.ts +325 -0
  160. package/ai/tools/deleteSpacesToolModel.ts +159 -0
  161. package/ai/tools/devReloadUtils.ts +29 -0
  162. package/ai/tools/dialogMessageSearch.ts +137 -0
  163. package/ai/tools/doctorSkillTool.ts +72 -0
  164. package/ai/tools/ecommerceScraperTool.ts +86 -0
  165. package/ai/tools/emailTools.ts +549 -0
  166. package/ai/tools/evalSkillTool.ts +92 -0
  167. package/ai/tools/exaSearchTool.ts +63 -0
  168. package/ai/tools/execShellTool.ts +266 -0
  169. package/ai/tools/executeSqlTool.ts +192 -0
  170. package/ai/tools/fetchWebpageSupport.ts +333 -0
  171. package/ai/tools/fetchWebpageTool.ts +97 -0
  172. package/ai/tools/geminiImagePreviewTool.ts +386 -0
  173. package/ai/tools/generateDocxTool.ts +215 -0
  174. package/ai/tools/googleSearchScraperTool.ts +106 -0
  175. package/ai/tools/importDataTool.ts +133 -0
  176. package/ai/tools/importSkillTool.ts +162 -0
  177. package/ai/tools/index.ts +2290 -0
  178. package/ai/tools/jdProductScraperTool.ts +821 -0
  179. package/ai/tools/listUserSpacesTool.ts +113 -0
  180. package/ai/tools/localFilesTool.ts +276 -0
  181. package/ai/tools/marxistsOfflineBook.ts +253 -0
  182. package/ai/tools/modelUsageTools.ts +206 -0
  183. package/ai/tools/noloWorkspaceReadTools.ts +467 -0
  184. package/ai/tools/olmOcrTool.ts +33 -0
  185. package/ai/tools/openaiImageTool.ts +267 -0
  186. package/ai/tools/prepareTools.ts +193 -0
  187. package/ai/tools/readDocTool.ts +88 -0
  188. package/ai/tools/readFileTool.ts +214 -0
  189. package/ai/tools/readTool.ts +194 -0
  190. package/ai/tools/readXPostTool.ts +229 -0
  191. package/ai/tools/readXhsProfileTool.ts +638 -0
  192. package/ai/tools/rememberMemoryTool.ts +84 -0
  193. package/ai/tools/remotionVideoTool.ts +151 -0
  194. package/ai/tools/searchDialogMessagesTool.ts +222 -0
  195. package/ai/tools/searchWorkspaceTool.ts +259 -0
  196. package/ai/tools/skillFollowup.ts +86 -0
  197. package/ai/tools/surfWeatherTool.ts +169 -0
  198. package/ai/tools/table/addTableRowTool.ts +217 -0
  199. package/ai/tools/table/createTableTool.ts +326 -0
  200. package/ai/tools/table/rowTools.ts +386 -0
  201. package/ai/tools/table/schemaTools.ts +244 -0
  202. package/ai/tools/table/shareTableTool.ts +148 -0
  203. package/ai/tools/table/toolShared.ts +129 -0
  204. package/ai/tools/taobaoTmallProductScraperTool.ts +49 -0
  205. package/ai/tools/toolApiClient.ts +279 -0
  206. package/ai/tools/toolPacks.ts +19 -0
  207. package/ai/tools/toolResultError.ts +42 -0
  208. package/ai/tools/toolRunSlice.ts +303 -0
  209. package/ai/tools/toolSchemaCompatibility.ts +53 -0
  210. package/ai/tools/uiAskChoiceTool.ts +104 -0
  211. package/ai/tools/updateContentTitleTool.ts +84 -0
  212. package/ai/tools/updateDocTool.ts +105 -0
  213. package/ai/tools/updateUserPreferenceProfileTool.ts +153 -0
  214. package/ai/tools/wereadGatewayTool.ts +152 -0
  215. package/ai/tools/whisperTool.ts +76 -0
  216. package/ai/tools/writeFileTool.ts +213 -0
  217. package/ai/tools/youtubeScraperTool.ts +116 -0
  218. package/ai/tools/ziweiChartTool.ts +678 -0
  219. package/ai/types.ts +58 -0
  220. package/ai/workflow/workflowExecutor.ts +323 -0
  221. package/ai/workflow/workflowSlice.ts +73 -0
  222. package/ai/workflow/workflowTypes.ts +106 -0
  223. package/app/actions/syncAppRecord.ts +73 -0
  224. package/app/constants/animationSets.ts +21 -0
  225. package/app/constants/appEditor.ts +99 -0
  226. package/app/favorite/deletedFavoriteProjection.ts +31 -0
  227. package/app/favorite/favoriteSlice.ts +690 -0
  228. package/app/favorite/type.ts +43 -0
  229. package/app/hooks/deleteDbKey.ts +254 -0
  230. package/app/i18n/client.ts +13 -0
  231. package/app/i18n/i18n.base.ts +14 -0
  232. package/app/i18n/i18n.config.ts +77 -0
  233. package/app/i18n/index.ts +15 -0
  234. package/app/i18n/mapLanguage.ts +11 -0
  235. package/app/i18n/translations/appBuilder.locale.ts +453 -0
  236. package/app/i18n/translations/error.locale.ts +246 -0
  237. package/app/i18n/translations/interface.locale.ts +2206 -0
  238. package/app/i18n/translations/pricing.locale.ts +397 -0
  239. package/app/i18n/translations/privacy.locale.ts +168 -0
  240. package/app/i18n/translations/seo.locale.ts +129 -0
  241. package/app/i18n/translations/terms.locale.ts +124 -0
  242. package/app/i18n/types.ts +6 -0
  243. package/app/notifications/model.ts +77 -0
  244. package/app/notifications/notificationSlice.ts +141 -0
  245. package/app/reducer.ts +36 -0
  246. package/app/settings/dbActionThunks.ts +34 -0
  247. package/app/settings/defaultSpacePreference.ts +87 -0
  248. package/app/settings/settingSlice.tsx +1212 -0
  249. package/app/settings/settingsRecord.ts +8 -0
  250. package/app/stateViews/runtime.ts +90 -0
  251. package/app/store.ts +55 -0
  252. package/app/theme/colors.ts +280 -0
  253. package/app/theme/fontPreference.ts +77 -0
  254. package/app/theme/theme.config.ts +120 -0
  255. package/app/theme/themeModeBootstrap.ts +123 -0
  256. package/app/types/appSummary.ts +118 -0
  257. package/app/types.ts +358 -0
  258. package/app/utils/appKeys.ts +55 -0
  259. package/app/utils/async.ts +28 -0
  260. package/app/utils/desktopAgentRuntimeTurnClient.ts +75 -0
  261. package/app/utils/env.ts +17 -0
  262. package/app/utils/fileUtils.ts +229 -0
  263. package/app/utils/imageUtils.ts +274 -0
  264. package/app/utils/myContentItems.ts +289 -0
  265. package/app/utils/retryAfter.ts +36 -0
  266. package/app/utils/retryFetch.ts +61 -0
  267. package/app/utils/toast.ts +3 -0
  268. package/auth/action/signUpAction.ts +227 -0
  269. package/auth/adminPermissions.ts +78 -0
  270. package/auth/authSlice.ts +531 -0
  271. package/auth/client/loginRequest.ts +14 -0
  272. package/auth/resetAuthScopedClientState.ts +27 -0
  273. package/auth/routes.ts +183 -0
  274. package/auth/token.ts +63 -0
  275. package/auth/types.ts +40 -0
  276. package/chat/chat.locale.ts +817 -0
  277. package/chat/dialog/actions/addCybotAction.ts +52 -0
  278. package/chat/dialog/actions/addReferenceKeysAction.ts +62 -0
  279. package/chat/dialog/actions/builtinDialogLlm.ts +35 -0
  280. package/chat/dialog/actions/cleanupCliSession.ts +40 -0
  281. package/chat/dialog/actions/createDialogAction.ts +379 -0
  282. package/chat/dialog/actions/createScheduledTaskAction.ts +78 -0
  283. package/chat/dialog/actions/handleSendMessageAction.ts +202 -0
  284. package/chat/dialog/actions/handleSendMessageResolver.ts +27 -0
  285. package/chat/dialog/actions/removeCybotAction.ts +6 -0
  286. package/chat/dialog/actions/removeDialogAgentAction.ts +44 -0
  287. package/chat/dialog/actions/replacePrimaryCybotAction.ts +6 -0
  288. package/chat/dialog/actions/setPrimaryDialogAgentAction.ts +52 -0
  289. package/chat/dialog/actions/updateDialogSummaryAction.ts +430 -0
  290. package/chat/dialog/actions/updateDialogTitleAction.ts +151 -0
  291. package/chat/dialog/actions/updateDialogTitlePolicy.ts +30 -0
  292. package/chat/dialog/actions/updateTokensAction.ts +233 -0
  293. package/chat/dialog/dialogAgents.ts +72 -0
  294. package/chat/dialog/dialogAttachmentCleanup.ts +135 -0
  295. package/chat/dialog/dialogSlice.ts +985 -0
  296. package/chat/dialog/dialogTitle.ts +81 -0
  297. package/chat/dialog/dialogTokenStats.ts +12 -0
  298. package/chat/dialog/dialogUrl.ts +6 -0
  299. package/chat/dialog/goal.ts +108 -0
  300. package/chat/dialog/objectAssistantRegistry.ts +286 -0
  301. package/chat/dialog/schedule.ts +17 -0
  302. package/chat/messages/activityCompletion.ts +97 -0
  303. package/chat/messages/fetchAndCacheMessages.ts +119 -0
  304. package/chat/messages/fetchConvMsgs.ts +51 -0
  305. package/chat/messages/fileUrl.ts +13 -0
  306. package/chat/messages/imagePayloadPersistence.ts +22 -0
  307. package/chat/messages/messageAgent.ts +8 -0
  308. package/chat/messages/messageContent.ts +203 -0
  309. package/chat/messages/messageContract.ts +88 -0
  310. package/chat/messages/messageSlice.ts +1386 -0
  311. package/chat/messages/toolThunks.ts +646 -0
  312. package/chat/messages/types.ts +8 -1
  313. package/chat/messages/web/toolDisplayName.ts +686 -0
  314. package/cli/agentAliases.ts +29 -9
  315. package/cli/agentInternalCommandEntries.ts +11 -3
  316. package/cli/agentMachineCommands.ts +1 -0
  317. package/cli/agentRecordCommands.ts +2 -2
  318. package/cli/agentRecordHelpers.ts +59 -6
  319. package/cli/agentRunCommand.ts +84 -19
  320. package/cli/client/agentRun.ts +92 -261
  321. package/cli/client/localRuntimeAdapter.ts +292 -50
  322. package/cli/commandRegistry.ts +7 -4
  323. package/cli/dialogAttachmentCleanup.ts +151 -0
  324. package/cli/dialogCommands.ts +163 -61
  325. package/cli/dialogInternalCommandEntries.ts +1 -1
  326. package/cli/docCreateCommands.ts +345 -0
  327. package/cli/docInternalCommandEntries.ts +11 -0
  328. package/cli/docPageHelpers.ts +80 -0
  329. package/cli/docSkillHelpers.ts +67 -0
  330. package/cli/docSpaceHelpers.ts +46 -0
  331. package/cli/internalCommandEntries.ts +4 -0
  332. package/cli/machineCommands.ts +18 -34
  333. package/cli/memoryCommands.ts +253 -0
  334. package/cli/memoryInternalCommandEntries.ts +9 -0
  335. package/cli/qoderUsageProbe.ts +252 -0
  336. package/cli/scriptCommandEntries.ts +0 -3
  337. package/cli/secretScan.ts +31 -0
  338. package/cli/tableCommands.ts +248 -13
  339. package/cli/workflowInternalCommandEntries.ts +2 -3
  340. package/client/agentRun.test.ts +119 -83
  341. package/client/agentRun.ts +92 -261
  342. package/client/localRuntimeAdapter.test.ts +894 -32
  343. package/client/localRuntimeAdapter.ts +292 -50
  344. package/commandRegistry.ts +7 -4
  345. package/connector-experimental/capabilities.ts +10 -9
  346. package/core/builtinAgents.ts +209 -0
  347. package/core/config.ts +15 -0
  348. package/core/crypto.ts +51 -0
  349. package/core/generateKeyPairFromSeedV1.ts +15 -0
  350. package/core/generateMainKey.ts +22 -0
  351. package/core/init.ts +41 -0
  352. package/core/localOrigins.ts +8 -0
  353. package/core/password.ts +13 -0
  354. package/core/prefix.ts +23 -0
  355. package/create/editor/transforms/fromMarkdown/index.ts +260 -0
  356. package/create/editor/transforms/fromMarkdown/inline.ts +285 -0
  357. package/create/editor/transforms/fromMarkdown/table.ts +130 -0
  358. package/create/editor/transforms/markdownToSlate.ts +24 -0
  359. package/create/editor/transforms/slateToRenderMarkdown.ts +218 -0
  360. package/create/editor/transforms/slateToSimplifiedMarkdown.ts +224 -0
  361. package/create/editor/transforms/slateToText.ts +33 -0
  362. package/create/editor/utils/slateUtils.ts +233 -0
  363. package/create/space/addSpaceAction.ts +193 -0
  364. package/create/space/category/categoryActions.ts +427 -0
  365. package/create/space/changeSpaceAction.ts +36 -0
  366. package/create/space/constants.ts +8 -0
  367. package/create/space/content/addContentAction.ts +116 -0
  368. package/create/space/content/contentThunks.ts +90 -0
  369. package/create/space/content/deleteContentFromSpaceAction.ts +187 -0
  370. package/create/space/content/deleteMultipleContentAction.ts +112 -0
  371. package/create/space/content/moveContentAction.ts +285 -0
  372. package/create/space/content/updateContentCategoryAction.ts +154 -0
  373. package/create/space/content/updateContentTitleAction.ts +151 -0
  374. package/create/space/content/uploadAndAddFileToSpaceAction.ts +98 -0
  375. package/create/space/contentKeyUtils.ts +117 -0
  376. package/create/space/deleteSpaceAction.ts +276 -0
  377. package/create/space/fetchSpaceAction.ts +70 -0
  378. package/create/space/fetchSpaceSidebarStateAction.ts +26 -0
  379. package/create/space/loadDefaultSpaceAction.ts +57 -0
  380. package/create/space/member/addMemberAction.ts +79 -0
  381. package/create/space/member/fetchUserSpaceMembershipsAction.ts +386 -0
  382. package/create/space/member/memberThunks.ts +47 -0
  383. package/create/space/member/removeMemberAction.ts +67 -0
  384. package/create/space/resolvePreferredSpaceId.ts +113 -0
  385. package/create/space/sidebarVisibleTypes.ts +260 -0
  386. package/create/space/space.locale.ts +1087 -0
  387. package/create/space/spaceAccess.ts +182 -0
  388. package/create/space/spaceCollapsedState.ts +54 -0
  389. package/create/space/spaceKeys.ts +65 -0
  390. package/create/space/spaceSlice.ts +328 -0
  391. package/create/space/spaceThunks.ts +410 -0
  392. package/create/space/types.ts +27 -0
  393. package/create/space/updateSpaceAction.ts +107 -0
  394. package/create/space/utils/permissions.ts +47 -0
  395. package/create/types.ts +21 -0
  396. package/database/actions/agentReadResolution.ts +33 -0
  397. package/database/actions/common.ts +243 -0
  398. package/database/actions/deleteFile.ts +40 -0
  399. package/database/actions/fileContent.ts +125 -0
  400. package/database/actions/patch.ts +155 -0
  401. package/database/actions/read.ts +358 -0
  402. package/database/actions/readAndWait.ts +260 -0
  403. package/database/actions/readRequestManager.ts +120 -0
  404. package/database/actions/readResolution.ts +125 -0
  405. package/database/actions/remove.ts +94 -0
  406. package/database/actions/replication.ts +477 -0
  407. package/database/actions/upload.ts +186 -0
  408. package/database/actions/upsert.ts +56 -0
  409. package/database/actions/write.ts +146 -0
  410. package/database/authority/ownerKey.ts +80 -0
  411. package/database/authority/recordAuthority.ts +67 -0
  412. package/database/authority/userAuthorityRegistry.ts +54 -0
  413. package/database/client/fetchUserData.ts +61 -0
  414. package/database/dbActionThunks.ts +1 -0
  415. package/database/dbSlice.ts +149 -0
  416. package/database/fileRing.ts +51 -0
  417. package/database/fileStorage.ts +232 -0
  418. package/database/fileUrl.ts +34 -0
  419. package/database/keys.ts +767 -0
  420. package/database/queryPrefixes.ts +14 -0
  421. package/database/requests.ts +443 -0
  422. package/database/runtimeServerContext.ts +54 -0
  423. package/database/tenantPlacement.ts +57 -0
  424. package/database/userPreferenceRegister.ts +131 -0
  425. package/database/utils/ulid.ts +1 -0
  426. package/dialogAttachmentCleanup.ts +151 -0
  427. package/dialogCommands.ts +163 -61
  428. package/dialogInternalCommandEntries.ts +1 -1
  429. package/docCreateCommands.ts +345 -0
  430. package/docInternalCommandEntries.ts +11 -0
  431. package/docPageHelpers.ts +80 -0
  432. package/docSkillHelpers.ts +67 -0
  433. package/docSpaceHelpers.ts +46 -0
  434. package/integrations/anthropic/anthropicModels.ts +47 -0
  435. package/integrations/deepseek/models.ts +37 -0
  436. package/integrations/google/models.ts +341 -0
  437. package/integrations/openai/chatCompletionStreamMode.ts +10 -0
  438. package/integrations/openai/filterAndCleanMessages.ts +284 -0
  439. package/integrations/openai/flexTier.ts +102 -0
  440. package/integrations/openai/generateOpenAIRequestBody.ts +271 -0
  441. package/integrations/openai/generateResponseRequestBody.ts +77 -0
  442. package/integrations/openai/models.ts +271 -0
  443. package/integrations/openai/providerBodyCompatibility.ts +23 -0
  444. package/integrations/openai/responsesHelpers.ts +297 -0
  445. package/integrations/x-reader/types.ts +109 -0
  446. package/integrations/xai/models.ts +13 -0
  447. package/integrations/xhs-reader/redaction.ts +68 -0
  448. package/integrations/xhs-reader/types.ts +277 -0
  449. package/integrations/xhs-reader/url.ts +80 -0
  450. package/internalCommandEntries.ts +4 -0
  451. package/machineCommands.ts +18 -34
  452. package/memoryCommands.ts +253 -0
  453. package/memoryInternalCommandEntries.ts +9 -0
  454. package/package.json +454 -9
  455. package/qoderUsageProbe.ts +252 -0
  456. package/render/contentIcon/types.ts +167 -0
  457. package/render/page/createPageAction.ts +183 -0
  458. package/render/page/docSlice.ts +495 -0
  459. package/render/page/types.ts +19 -0
  460. package/render/table/createTableAction.ts +274 -0
  461. package/render/table/deleteTableAction.ts +193 -0
  462. package/render/table/fetchAndCacheTableRows.ts +174 -0
  463. package/render/table/tableSlice.ts +1167 -0
  464. package/render/table/toolValueUtils.ts +363 -0
  465. package/render/table/types.ts +262 -0
  466. package/render/table/utils/tableSerialization.ts +50 -0
  467. package/scriptCommandEntries.ts +0 -3
  468. package/secretScan.ts +31 -0
  469. package/server/handlers/agentRun/types.ts +105 -0
  470. package/share/action.ts +225 -0
  471. package/share/helpers.ts +302 -0
  472. package/share/keys.ts +243 -0
  473. package/share/publicSharePolicy.ts +27 -0
  474. package/share/shareSlice.ts +53 -0
  475. package/share/types.ts +100 -0
  476. package/tableCommands.ts +248 -13
  477. package/workflowInternalCommandEntries.ts +2 -3
  478. package/ai/tools/agent/taskRunTool.ts +0 -112
  479. package/cli/client/taskRunPrompt.ts +0 -27
  480. package/cli/taskRunCommand.ts +0 -265
  481. package/client/taskRunPrompt.ts +0 -27
  482. package/taskRunCommand.ts +0 -265
@@ -55,6 +55,11 @@ function parseOutputMode(raw: string): OutputMode {
55
55
  throw new Error(`--output must be one of full, raw, items, json, jsonl; got ${raw}`);
56
56
  }
57
57
 
58
+ function resolveQueryColumns(columns: string[] | undefined, includeActivity: boolean): string[] | undefined {
59
+ if (!includeActivity) return columns;
60
+ return Array.isArray(columns) ? includeTableActivityColumns(columns) : undefined;
61
+ }
62
+
58
63
  function parseTableArg(raw: string): { tenantId?: string; tableId?: string } {
59
64
  const trimmed = raw.trim();
60
65
  if (!trimmed) return {};
@@ -66,6 +71,32 @@ function parseTableArg(raw: string): { tenantId?: string; tableId?: string } {
66
71
  };
67
72
  }
68
73
 
74
+ function normalizeSpaceInput(raw: string): string {
75
+ const value = raw.trim();
76
+ if (!value) return "";
77
+ if (value.startsWith("http://") || value.startsWith("https://")) {
78
+ const match = new URL(value).pathname.match(/^\/space\/([^/]+)/);
79
+ return match?.[1] ? decodeURIComponent(match[1]).replace(/^space-/, "") : "";
80
+ }
81
+ return value.replace(/^space-/, "");
82
+ }
83
+
84
+ function getSpaceContentKeys(spaceRecord: any): Set<string> {
85
+ const keys = new Set<string>();
86
+ const contents = spaceRecord?.contents;
87
+ if (!contents || typeof contents !== "object") return keys;
88
+ for (const [entryKey, value] of Object.entries(contents)) {
89
+ keys.add(entryKey);
90
+ if (value && typeof value === "object") {
91
+ const contentKey = (value as any).contentKey;
92
+ if (typeof contentKey === "string" && contentKey.trim()) {
93
+ keys.add(contentKey.trim());
94
+ }
95
+ }
96
+ }
97
+ return keys;
98
+ }
99
+
69
100
  function resolveServerUrl(args: string[], env: EnvLike): string {
70
101
  return (
71
102
  readOption(args, "--server-url") ||
@@ -89,16 +120,46 @@ function resolveAuthToken(args: string[], env: EnvLike): string {
89
120
  }
90
121
 
91
122
  function parseJwtTenantId(token: string): string | undefined {
92
- const [, payload] = token.split(".");
93
- if (!payload) return undefined;
94
- try {
95
- const normalized = payload.replace(/-/g, "+").replace(/_/g, "/");
96
- const decoded = Buffer.from(normalized, "base64").toString("utf8");
97
- const parsed = JSON.parse(decoded);
98
- return typeof parsed.userId === "string" ? parsed.userId : typeof parsed.sub === "string" ? parsed.sub : undefined;
99
- } catch {
100
- return undefined;
123
+ for (const parsed of parseJwtPayloadCandidates(token)) {
124
+ const userId = parsed.userId;
125
+ const sub = parsed.sub;
126
+ if (typeof userId === "string" && userId) return userId;
127
+ if (typeof sub === "string" && sub) return sub;
101
128
  }
129
+ return undefined;
130
+ }
131
+
132
+ function parseJwtUsername(token: string): string | undefined {
133
+ for (const parsed of parseJwtPayloadCandidates(token)) {
134
+ const username = parsed.username;
135
+ if (typeof username === "string" && username.trim()) return username.trim();
136
+ }
137
+ return undefined;
138
+ }
139
+
140
+ function parseJwtPayloadCandidates(token: string): Array<Record<string, unknown>> {
141
+ const trimmed = token.trim();
142
+ if (!trimmed) return [];
143
+ const parts = trimmed.split(".").filter(Boolean);
144
+ const payloadCandidates = parts.length >= 3 ? [parts[1], parts[0]] : [parts[0]];
145
+ const parsed: Array<Record<string, unknown>> = [];
146
+ for (const payload of payloadCandidates) {
147
+ try {
148
+ const decoded = Buffer.from(payload, "base64").toString("utf8");
149
+ const value = JSON.parse(decoded);
150
+ if (value && typeof value === "object" && !Array.isArray(value)) {
151
+ parsed.push(value as Record<string, unknown>);
152
+ }
153
+ } catch {}
154
+ }
155
+ return parsed;
156
+ }
157
+
158
+ function resolveUserId(args: string[], env: EnvLike, authToken: string): string | undefined {
159
+ const explicit = readOption(args, "--tenant-id") || env.USER_ID || parseJwtTenantId(authToken);
160
+ if (explicit) return explicit;
161
+ const username = parseJwtUsername(authToken);
162
+ return username && /^[a-z0-9_-]+$/i.test(username) ? username : undefined;
102
163
  }
103
164
 
104
165
  function formatOutput(input: { envelope: any; rawData: any; mode: OutputMode }): string {
@@ -133,6 +194,182 @@ function usage(): string {
133
194
  ].join("\n");
134
195
  }
135
196
 
197
+ function listUsage(): string {
198
+ return [
199
+ "Usage:",
200
+ " nolo table list [--limit <n>] [--title-query <text>] [--purpose <purpose>] [--output full|raw|items|json|jsonl]",
201
+ "",
202
+ ].join("\n");
203
+ }
204
+
205
+ function tableHasPurpose(table: any, purpose: string): boolean {
206
+ return typeof table?.purpose === "string" && table.purpose.toLowerCase() === purpose.toLowerCase();
207
+ }
208
+
209
+ function getComparableUpdatedAt(record: any): number {
210
+ const raw = record?.updatedAt ?? record?.updated_at ?? record?.createdAt ?? record?.created;
211
+ if (typeof raw === "number" && Number.isFinite(raw)) return raw;
212
+ if (typeof raw === "string") return Date.parse(raw) || 0;
213
+ return 0;
214
+ }
215
+
216
+ function formatTableListOutput(args: {
217
+ mode: OutputMode;
218
+ tables: any[];
219
+ envelope: any;
220
+ }) {
221
+ if (args.mode === "full") return JSON.stringify(args.envelope, null, 2);
222
+ if (args.mode === "raw") return JSON.stringify(args.tables, null, 2);
223
+ if (args.mode === "items") return JSON.stringify(args.tables, null, 2);
224
+ return args.tables.map((item) => JSON.stringify(item)).join("\n");
225
+ }
226
+
227
+ export async function runTableListCommand(args: string[], deps: TableCommandDeps = {}): Promise<number> {
228
+ const env = deps.env ?? process.env;
229
+ const output = deps.output ?? process.stdout;
230
+ const fetchImpl = deps.fetchImpl ?? fetch;
231
+ if (hasFlag(args, "--help") || hasFlag(args, "-h")) {
232
+ output.write(listUsage());
233
+ return 0;
234
+ }
235
+
236
+ let outputMode: OutputMode;
237
+ try {
238
+ outputMode = parseOutputMode(readOption(args, "--output") || "items");
239
+ } catch (error) {
240
+ output.write(`[nolo] table list failed: ${error instanceof Error ? error.message : String(error)}\n`);
241
+ return 1;
242
+ }
243
+
244
+ const authToken = resolveAuthToken(args, env);
245
+ const userId = resolveUserId(args, env, authToken);
246
+ if (!userId) {
247
+ output.write("[nolo] table list failed: user id is required. Pass --tenant-id or use a login token.\n");
248
+ return 1;
249
+ }
250
+ if (!authToken) {
251
+ output.write("[nolo] table list failed: AUTH_TOKEN is required.\n");
252
+ return 1;
253
+ }
254
+
255
+ const limit = Math.max(1, Math.min(Number(readOption(args, "--limit") || 50), 200));
256
+ const titleQuery = readOption(args, "--title-query").trim().toLowerCase();
257
+ const purpose = readOption(args, "--purpose").trim();
258
+ const spaceId = normalizeSpaceInput(readOption(args, "--space") || readOption(args, "--space-id"));
259
+ const scanLimit = titleQuery || purpose ? Math.max(limit * 5, 200) : limit;
260
+ const serverUrl = resolveServerUrl(args, env);
261
+
262
+ let records: any[];
263
+ try {
264
+ records = spaceId
265
+ ? await fetchSpaceTableRecords({
266
+ authToken,
267
+ fetchImpl,
268
+ serverUrl,
269
+ spaceId,
270
+ })
271
+ : await fetchUserTableRecords({
272
+ authToken,
273
+ fetchImpl,
274
+ limit: Math.min(scanLimit, 500),
275
+ serverUrl,
276
+ userId,
277
+ });
278
+ } catch (error) {
279
+ output.write(`[nolo] table list failed: ${error instanceof Error ? error.message : String(error)}\n`);
280
+ return 1;
281
+ }
282
+ const tables = records
283
+ .filter((table: any) => table && typeof table === "object" && !table.deletedAt)
284
+ .filter((table: any) => !titleQuery || String(table.displayName ?? table.name ?? table.title ?? "").toLowerCase().includes(titleQuery))
285
+ .filter((table: any) => !purpose || tableHasPurpose(table, purpose))
286
+ .sort((left: any, right: any) => getComparableUpdatedAt(right) - getComparableUpdatedAt(left))
287
+ .slice(0, limit)
288
+ .map((table: any) => ({
289
+ dbKey: table.dbKey ?? null,
290
+ tableId: table.tableId ?? null,
291
+ displayName: table.displayName ?? table.name ?? table.title ?? "(untitled)",
292
+ spaceId: table.spaceId ?? null,
293
+ tenantId: table.tenantId ?? null,
294
+ columnCount: Array.isArray(table.columns) ? table.columns.length : 0,
295
+ createdAt: table.createdAt ?? null,
296
+ updatedAt: table.updatedAt ?? table.updated_at ?? null,
297
+ }));
298
+
299
+ const envelope = { success: true, userId, ...(spaceId ? { space: spaceId } : {}), total: tables.length, tables };
300
+ output.write(`${formatTableListOutput({ mode: outputMode, tables, envelope })}\n`);
301
+ return 0;
302
+ }
303
+
304
+ async function readJsonResponse(response: Response) {
305
+ const text = await response.text();
306
+ let payload: any;
307
+ try {
308
+ payload = text ? JSON.parse(text) : {};
309
+ } catch {
310
+ if (!response.ok) throw new Error(text || response.statusText);
311
+ return text;
312
+ }
313
+ if (!response.ok || payload?.error) {
314
+ throw new Error(payload?.error ?? response.statusText);
315
+ }
316
+ return payload;
317
+ }
318
+
319
+ async function fetchUserTableRecords(args: {
320
+ authToken: string;
321
+ fetchImpl: typeof fetch;
322
+ limit: number;
323
+ serverUrl: string;
324
+ userId: string;
325
+ }) {
326
+ const response = await args.fetchImpl(
327
+ `${args.serverUrl}/api/v1/db/query/${encodeURIComponent(args.userId)}?limit=${args.limit}`,
328
+ {
329
+ method: "POST",
330
+ headers: {
331
+ Authorization: `Bearer ${args.authToken}`,
332
+ "Content-Type": "application/json",
333
+ },
334
+ body: JSON.stringify({ type: "table" }),
335
+ }
336
+ );
337
+ const payload = await readJsonResponse(response);
338
+ return Array.isArray(payload?.data?.data)
339
+ ? payload.data.data
340
+ : Array.isArray(payload?.data)
341
+ ? payload.data
342
+ : [];
343
+ }
344
+
345
+ async function fetchSpaceTableRecords(args: {
346
+ authToken: string;
347
+ fetchImpl: typeof fetch;
348
+ serverUrl: string;
349
+ spaceId: string;
350
+ }) {
351
+ const readRecord = async (dbKey: string) => {
352
+ const response = await args.fetchImpl(
353
+ `${args.serverUrl}/api/v1/db/read/${encodeURIComponent(dbKey)}`,
354
+ { headers: { Authorization: `Bearer ${args.authToken}` } }
355
+ );
356
+ const payload = await readJsonResponse(response);
357
+ return payload?.data ?? payload;
358
+ };
359
+ const space = await readRecord(`space-${args.spaceId}`);
360
+ const tableKeys = [...getSpaceContentKeys(space)].filter((key) => key.startsWith("meta-"));
361
+ const records = await Promise.all(
362
+ tableKeys.map(async (key) => {
363
+ try {
364
+ return await readRecord(key);
365
+ } catch {
366
+ return null;
367
+ }
368
+ })
369
+ );
370
+ return records.filter(Boolean);
371
+ }
372
+
136
373
  export async function runTableQueryCommand(args: string[], deps: TableCommandDeps = {}): Promise<number> {
137
374
  const env = deps.env ?? process.env;
138
375
  const output = deps.output ?? process.stdout;
@@ -159,7 +396,7 @@ export async function runTableQueryCommand(args: string[], deps: TableCommandDep
159
396
 
160
397
  const tableArg = parseTableArg(readOption(args, "--table"));
161
398
  const authToken = resolveAuthToken(args, env);
162
- const tenantId = readOption(args, "--tenant-id") || tableArg.tenantId || env.USER_ID || parseJwtTenantId(authToken);
399
+ const tenantId = readOption(args, "--tenant-id") || tableArg.tenantId || resolveUserId(args, env, authToken);
163
400
  const tableId = tableArg.tableId;
164
401
  const hasSingleRowShortcut = Boolean(readOption(args, "--row") || readOption(args, "--row-id") || readOption(args, "--row-dbkey"));
165
402
  if (!tenantId || !tableId) {
@@ -184,9 +421,7 @@ export async function runTableQueryCommand(args: string[], deps: TableCommandDep
184
421
  tenantId,
185
422
  tableId,
186
423
  filters: filters ?? {},
187
- columns: hasFlag(args, "--include-activity")
188
- ? includeTableActivityColumns(columns)
189
- : columns,
424
+ columns: resolveQueryColumns(columns, hasFlag(args, "--include-activity")),
190
425
  includeBaseFields: !hasFlag(args, "--no-base-fields"),
191
426
  limit: Number(readOption(args, "--limit") || (hasSingleRowShortcut ? 1 : 20)),
192
427
  offset: Number(readOption(args, "--offset") || 0),
@@ -1,11 +1,10 @@
1
1
  import { createEnvCommand } from "./cliCommandFactories";
2
2
  import type { CommandEntry } from "./cliCommandTypes";
3
- import { runTableQueryCommand } from "./tableCommands";
4
- import { runTaskRunCommand } from "./taskRunCommand";
3
+ import { runTableListCommand, runTableQueryCommand } from "./tableCommands";
5
4
 
6
5
  export function getWorkflowInternalCommandEntries(): CommandEntry[] {
7
6
  return [
7
+ createEnvCommand(["table", "list"], "List table metadata", runTableListCommand),
8
8
  createEnvCommand(["table", "query"], "Query table rows", runTableQueryCommand),
9
- createEnvCommand(["task-run"], "Update durable task-run state through the runner bridge", runTaskRunCommand),
10
9
  ];
11
10
  }
@@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test";
2
2
  import { Writable } from "node:stream";
3
3
 
4
4
  import {
5
- classifyTaskRunReviewStatus,
5
+ classifyTaskContextReviewStatus,
6
6
  findServerPlatformTools,
7
7
  runAgentTurn,
8
8
  } from "./agentRun";
@@ -24,14 +24,14 @@ class CaptureOutput extends Writable {
24
24
 
25
25
  describe("cli agent run client", () => {
26
26
  test("classifies only clear reviewer outcomes", () => {
27
- expect(classifyTaskRunReviewStatus("Review decision: passed")).toBe("passed");
28
- expect(classifyTaskRunReviewStatus("Review decision: needs_changes")).toBe("needs_changes");
29
- expect(classifyTaskRunReviewStatus("Review decision: blocked")).toBe("blocked");
30
- expect(classifyTaskRunReviewStatus("LGTM, no issues found")).toBe("passed");
31
- expect(classifyTaskRunReviewStatus("Changes requested for missing test coverage")).toBe(
27
+ expect(classifyTaskContextReviewStatus("Review decision: passed")).toBe("passed");
28
+ expect(classifyTaskContextReviewStatus("Review decision: needs_changes")).toBe("needs_changes");
29
+ expect(classifyTaskContextReviewStatus("Review decision: blocked")).toBe("blocked");
30
+ expect(classifyTaskContextReviewStatus("LGTM, no issues found")).toBe("passed");
31
+ expect(classifyTaskContextReviewStatus("Changes requested for missing test coverage")).toBe(
32
32
  "needs_changes"
33
33
  );
34
- expect(classifyTaskRunReviewStatus("I looked at the diff and have notes")).toBeUndefined();
34
+ expect(classifyTaskContextReviewStatus("I looked at the diff and have notes")).toBeUndefined();
35
35
  });
36
36
 
37
37
  test("identifies server platform tools that local runtime cannot provide", () => {
@@ -111,18 +111,23 @@ describe("cli agent run client", () => {
111
111
  reason: "connector_execution_failed",
112
112
  code: "connector_disconnected_mid_run",
113
113
  message: "Connector disconnected for machine: machine-win",
114
+ dialogId: "dialog-failed-1",
114
115
  }, { status: 502 }),
115
116
  });
116
117
 
117
- expect(result).toEqual({ exitCode: 1 });
118
+ expect(result).toEqual({ exitCode: 1, dialogId: "dialog-failed-1" });
118
119
  expect(output.text()).toContain("[nolo] Agent request failed: HTTP 502");
119
120
  expect(output.text()).toContain("Connector execution failed");
120
121
  expect(output.text()).toContain("Connector disconnected for machine: machine-win");
121
122
  expect(output.text()).toContain("code=connector_disconnected_mid_run");
122
123
  expect(output.text()).toContain("reason=connector_execution_failed");
124
+ expect(output.text()).toContain("[nolo] failed dialog: dialog-failed-1");
125
+ expect(output.text()).toContain(
126
+ 'nolo agent run agent-win-codex --continue dialog-failed-1 --msg "retry"'
127
+ );
123
128
  });
124
129
 
125
- test("prepends task-run context for HTTP agent runs", async () => {
130
+ test("converts task row context to subjectRefs without legacy prompt or runtime taskRun payload", async () => {
126
131
  const output = new CaptureOutput();
127
132
  const requests: Array<{ body: any }> = [];
128
133
 
@@ -135,10 +140,8 @@ describe("cli agent run client", () => {
135
140
  env: { AUTH_TOKEN: "token-123" },
136
141
  output,
137
142
  runtimeMode: "server",
138
- taskRunContext: {
143
+ taskRowContext: {
139
144
  rowDbKey: "row-b2e06f801f-01TASK",
140
- taskRunId: "taskrun-1",
141
- workItemId: "frontend-filter",
142
145
  artifactIds: ["artifact-1"],
143
146
  },
144
147
  fetchImpl: async (_url, init) => {
@@ -147,22 +150,17 @@ describe("cli agent run client", () => {
147
150
  },
148
151
  });
149
152
 
150
- expect(requests[0]?.body.userInput).toContain("AI-native task-run context:");
151
- expect(requests[0]?.body.userInput).toContain("current task board is only the present observation and validation use case");
152
- expect(requests[0]?.body.userInput).toContain("rowDbKey: row-b2e06f801f-01TASK");
153
- expect(requests[0]?.body.userInput).toContain("workItemId: frontend-filter");
154
- expect(requests[0]?.body.userInput).toContain("User task:\nFix the filter UI");
155
- expect(requests[0]?.body.runtimeContext.taskRun).toEqual({
156
- rowDbKey: "row-b2e06f801f-01TASK",
157
- taskRunId: "taskrun-1",
158
- workItemId: "frontend-filter",
159
- artifactIds: ["artifact-1"],
153
+ expect(requests[0]?.body.userInput).toBe("Fix the filter UI");
154
+ expect(requests[0]?.body.runtimeContext.taskRun).toBeUndefined();
155
+ expect(requests[0]?.body.runtimeContext.subjectRefs).toContainEqual({
156
+ kind: "table-row",
157
+ id: "row-b2e06f801f-01TASK",
158
+ role: "task",
160
159
  });
161
160
  });
162
161
 
163
- test("records task-run completion after an HTTP agent run returns a dialog", async () => {
162
+ test("does not write task-context completion after an HTTP agent run returns a dialog", async () => {
164
163
  const output = new CaptureOutput();
165
- const writebacks: any[] = [];
166
164
 
167
165
  const result = await runAgentTurn({
168
166
  agentName: "frontend-implementer",
@@ -173,12 +171,8 @@ describe("cli agent run client", () => {
173
171
  env: { AUTH_TOKEN: "token-123" },
174
172
  output,
175
173
  runtimeMode: "server",
176
- taskRunContext: {
174
+ taskRowContext: {
177
175
  rowDbKey: "row-b2e06f801f-01TASK",
178
- workItemId: "frontend-filter",
179
- },
180
- taskRunRecorder: async (args) => {
181
- writebacks.push(args);
182
176
  },
183
177
  fetchImpl: async () => {
184
178
  return Response.json({ content: "patched", dialogId: "dialog-1" });
@@ -186,16 +180,6 @@ describe("cli agent run client", () => {
186
180
  });
187
181
 
188
182
  expect(result).toEqual({ exitCode: 0, dialogId: "dialog-1" });
189
- expect(writebacks).toHaveLength(1);
190
- expect(writebacks[0]).toMatchObject({
191
- status: "completed",
192
- dialogId: "dialog-1",
193
- resultSummary: "patched",
194
- });
195
- expect(writebacks[0].options.taskRunContext).toEqual({
196
- rowDbKey: "row-b2e06f801f-01TASK",
197
- workItemId: "frontend-filter",
198
- });
199
183
  });
200
184
 
201
185
  test("sends image inputs as multimodal userInput over HTTP", async () => {
@@ -237,6 +221,7 @@ describe("cli agent run client", () => {
237
221
  category: "manual-checks",
238
222
  inheritedFromDialogKey: "dialog-user-1-dialog-2",
239
223
  parentDialogId: "dialog-2",
224
+ subjectDialogKey: "01SUBJECTDIALOG",
240
225
  background: true,
241
226
  noStream: true,
242
227
  timeoutMs: 600000,
@@ -261,12 +246,45 @@ describe("cli agent run client", () => {
261
246
  timeoutMs: 600000,
262
247
  stream: false,
263
248
  });
249
+ expect(requests[0]?.body.runtimeContext.subjectRefs).toEqual([
250
+ { kind: "dialog", id: "01SUBJECTDIALOG", role: "subject" },
251
+ ]);
264
252
  expect(result).toEqual({ exitCode: 0, dialogId: "dialog-1" });
265
253
  });
266
254
 
267
- test("records background task-run handoff as running instead of completed", async () => {
255
+ test("sends explicit subject refs over HTTP for review evidence", async () => {
256
+ const output = new CaptureOutput();
257
+ const requests: Array<{ body: any }> = [];
258
+
259
+ await runAgentTurn({
260
+ agentName: "reviewer",
261
+ agentKey: "agent-reviewer",
262
+ serverUrl: "https://nolo.chat",
263
+ message: "Review this implementation",
264
+ subjectRefs: [
265
+ { kind: "table-row", id: "row-user-board-task", role: "subject" },
266
+ { kind: "dialog", id: "dialog-impl", role: "review-target" },
267
+ { kind: "external", id: "commit:abc123", role: "commit" },
268
+ ],
269
+ scriptDir: "C:/missing/scripts",
270
+ env: { AUTH_TOKEN: "token-123" },
271
+ output,
272
+ runtimeMode: "server",
273
+ fetchImpl: async (_url, init) => {
274
+ requests.push({ body: JSON.parse(String(init?.body)) });
275
+ return Response.json({ content: "queued", dialogId: "dialog-review" });
276
+ },
277
+ });
278
+
279
+ expect(requests[0]?.body.runtimeContext.subjectRefs).toEqual([
280
+ { kind: "table-row", id: "row-user-board-task", role: "subject" },
281
+ { kind: "dialog", id: "dialog-impl", role: "review-target" },
282
+ { kind: "external", id: "commit:abc123", role: "commit" },
283
+ ]);
284
+ });
285
+
286
+ test("does not write background handoff state", async () => {
268
287
  const output = new CaptureOutput();
269
- const writebacks: any[] = [];
270
288
 
271
289
  const result = await runAgentTurn({
272
290
  agentName: "frontend-implementer",
@@ -278,12 +296,8 @@ describe("cli agent run client", () => {
278
296
  runtimeMode: "server",
279
297
  background: true,
280
298
  noStream: true,
281
- taskRunContext: {
299
+ taskRowContext: {
282
300
  rowDbKey: "row-b2e06f801f-01TASK",
283
- workItemId: "self",
284
- },
285
- taskRunRecorder: async (args) => {
286
- writebacks.push(args);
287
301
  },
288
302
  output,
289
303
  fetchImpl: async () => {
@@ -292,11 +306,6 @@ describe("cli agent run client", () => {
292
306
  });
293
307
 
294
308
  expect(result).toEqual({ exitCode: 0, dialogId: "dialog-bg" });
295
- expect(writebacks).toHaveLength(1);
296
- expect(writebacks[0]).toMatchObject({
297
- status: "running",
298
- dialogId: "dialog-bg",
299
- });
300
309
  });
301
310
 
302
311
  test("runs forced local turns through the injected runtime adapter without HTTP", async () => {
@@ -571,12 +580,12 @@ describe("cli agent run client", () => {
571
580
  round: 1,
572
581
  tool: "execShell",
573
582
  summary: expect.stringContaining("exit=0"),
583
+ metadata: { exitCode: 0 },
574
584
  });
575
585
  });
576
586
 
577
- test("passes local tool evidence to task-run writeback", async () => {
587
+ test("does not pass local tool evidence to an external writeback path", async () => {
578
588
  const output = new CaptureOutput();
579
- const writebacks: any[] = [];
580
589
  let completeCalls = 0;
581
590
 
582
591
  const result = await runAgentTurn({
@@ -588,12 +597,8 @@ describe("cli agent run client", () => {
588
597
  env: { AUTH_TOKEN: "token-123" },
589
598
  output,
590
599
  runtimeMode: "local",
591
- taskRunContext: {
600
+ taskRowContext: {
592
601
  rowDbKey: "row-b2e06f801f-01TASK",
593
- workItemId: "self",
594
- },
595
- taskRunRecorder: async (args) => {
596
- writebacks.push(args);
597
602
  },
598
603
  localRuntimeAdapter: {
599
604
  host: "cli",
@@ -630,21 +635,10 @@ describe("cli agent run client", () => {
630
635
  });
631
636
 
632
637
  expect(result).toMatchObject({ exitCode: 0, dialogId: "dialog-local" });
633
- expect(writebacks).toHaveLength(1);
634
- expect(writebacks[0].toolEvidence).toEqual({
635
- toolsUsed: ["readFile"],
636
- summary: {
637
- callCount: 1,
638
- resultCount: 1,
639
- errorCount: 0,
640
- rounds: 1,
641
- },
642
- });
643
638
  });
644
639
 
645
- test("records local background task-run handoff as running instead of completed", async () => {
640
+ test("does not write local background handoff state", async () => {
646
641
  const output = new CaptureOutput();
647
- const writebacks: any[] = [];
648
642
 
649
643
  const result = await runAgentTurn({
650
644
  agentName: "frontend",
@@ -656,12 +650,8 @@ describe("cli agent run client", () => {
656
650
  output,
657
651
  runtimeMode: "local",
658
652
  background: true,
659
- taskRunContext: {
653
+ taskRowContext: {
660
654
  rowDbKey: "row-b2e06f801f-01TASK",
661
- workItemId: "self",
662
- },
663
- taskRunRecorder: async (args) => {
664
- writebacks.push(args);
665
655
  },
666
656
  localRuntimeAdapter: {
667
657
  host: "cli",
@@ -685,12 +675,6 @@ describe("cli agent run client", () => {
685
675
  });
686
676
 
687
677
  expect(result).toEqual({ exitCode: 0, dialogId: "dialog-local-bg" });
688
- expect(writebacks).toHaveLength(1);
689
- expect(writebacks[0]).toMatchObject({
690
- status: "running",
691
- dialogId: "dialog-local-bg",
692
- });
693
- expect(writebacks[0].resultSummary).toBeUndefined();
694
678
  });
695
679
 
696
680
  test("auto mode prefers a working local runtime before HTTP", async () => {
@@ -887,6 +871,58 @@ describe("cli agent run client", () => {
887
871
  expect(output.text()).toContain("pm > server ok");
888
872
  });
889
873
 
874
+ test("auto mode keeps local runtime for CLI provider agents even when they declare platform tools", async () => {
875
+ const output = new CaptureOutput();
876
+ const httpCalls: string[] = [];
877
+ let providerCalled = false;
878
+
879
+ const result = await runAgentTurn({
880
+ agentName: "frontend-implementer",
881
+ agentKey: "frontend-implementer",
882
+ serverUrl: "https://nolo.chat",
883
+ message: "polish notifications",
884
+ scriptDir: "C:/missing/scripts",
885
+ env: { AUTH_TOKEN: "token-123" },
886
+ output,
887
+ runtimeMode: "auto",
888
+ localRuntimeAdapter: {
889
+ host: "cli",
890
+ capabilities: ["leveldb-agent-config", "local-provider", "local-tools"],
891
+ loadAgentConfig: async (agentRef) => ({
892
+ key: agentRef,
893
+ name: "AGY",
894
+ prompt: "Implement frontend tasks.",
895
+ provider: "agy",
896
+ cliProvider: "agy",
897
+ toolNames: ["streamParallelAgents", "queryTableRows"],
898
+ }),
899
+ loadDialogHistory: async () => [],
900
+ saveTurn: async () => ({ dialogId: "dialog-agy-auto-local" }),
901
+ resolveProvider: async () => ({
902
+ model: "agy",
903
+ complete: async () => {
904
+ providerCalled = true;
905
+ return { content: "agy local ok", model: "agy" };
906
+ },
907
+ }),
908
+ executeTool: async () => {
909
+ throw new Error("no tools expected");
910
+ },
911
+ },
912
+ fetchImpl: async (url) => {
913
+ httpCalls.push(String(url));
914
+ return Response.json({ content: "server" });
915
+ },
916
+ });
917
+
918
+ expect(providerCalled).toBe(true);
919
+ expect(result).toEqual({ exitCode: 0, dialogId: "dialog-agy-auto-local" });
920
+ expect(httpCalls).toEqual([]);
921
+ expect(output.text()).not.toContain("skipping local runtime");
922
+ expect(output.text()).toContain("frontend-implementer -> working locally");
923
+ expect(output.text()).toContain("frontend-implementer > agy local ok");
924
+ });
925
+
890
926
  test("auto mode does not skip monthly Mimo when a local shell cwd is already bound", async () => {
891
927
  const output = new CaptureOutput();
892
928
  const httpCalls: string[] = [];
@@ -1064,7 +1100,7 @@ describe("cli agent run client", () => {
1064
1100
  model: "fake-local",
1065
1101
  runtimeToolPolicy: {
1066
1102
  version: 1,
1067
- agentTools: ["queryTableRows", "taskRun"],
1103
+ agentTools: ["queryTableRows", "streamParallelAgents"],
1068
1104
  runtimeTools: ["execShell"],
1069
1105
  },
1070
1106
  }),
@@ -1089,7 +1125,7 @@ describe("cli agent run client", () => {
1089
1125
  expect(httpCalls).toHaveLength(1);
1090
1126
  expect(httpCalls[0]?.body.agentKey).toBe("agent-policy-platform-tools");
1091
1127
  expect(output.text()).toContain("auto runtime: skipping local runtime");
1092
- expect(output.text()).toContain("queryTableRows, taskRun");
1128
+ expect(output.text()).toContain("queryTableRows, streamParallelAgents");
1093
1129
  });
1094
1130
 
1095
1131
  test("auto mode skips known platform agents when local config cannot be read", async () => {