nolo-cli 0.1.13 → 0.1.14

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 (320) hide show
  1. package/README.md +9 -2
  2. package/agent-runtime/hostAdapter.ts +53 -0
  3. package/agent-runtime/index.ts +28 -0
  4. package/agent-runtime/localLoop.ts +62 -0
  5. package/agent-runtime/runtimeDecision.ts +70 -0
  6. package/agent-runtime/types.ts +87 -0
  7. package/agentRuntimeCommands.ts +139 -22
  8. package/agentRuntimeLocal.ts +7 -0
  9. package/ai/agent/_executeModel.ts +118 -0
  10. package/ai/agent/agentSlice.ts +544 -1
  11. package/ai/agent/appWorkingMemory.ts +126 -0
  12. package/ai/agent/avatarUtils.ts +24 -0
  13. package/ai/agent/buildEditingContext.ts +373 -0
  14. package/ai/agent/buildSystemPrompt.ts +532 -0
  15. package/ai/agent/cleanAgentMessages.ts +140 -0
  16. package/ai/agent/cliChatClient.ts +119 -0
  17. package/ai/agent/contextCompiler.ts +107 -0
  18. package/ai/agent/contextLayerContract.ts +44 -0
  19. package/ai/agent/createAgentSchema.ts +234 -0
  20. package/ai/agent/executeToolCall.ts +58 -0
  21. package/ai/agent/fetchAgentContexts.ts +42 -0
  22. package/ai/agent/generatePrompt.ts +3 -0
  23. package/ai/agent/getFullChatContextKeys.ts +168 -0
  24. package/ai/agent/hooks/fetchPublicAgents.ts +133 -0
  25. package/ai/agent/hooks/useAgentConfig.ts +61 -0
  26. package/ai/agent/hooks/useAgentDialog.ts +35 -0
  27. package/ai/agent/hooks/useAgentFormValidation.ts +202 -0
  28. package/ai/agent/hooks/usePublicAgents.ts +473 -0
  29. package/ai/agent/persistMessageWithFixedId.ts +37 -0
  30. package/ai/agent/planSlice.ts +259 -0
  31. package/ai/agent/referenceUtils.ts +229 -0
  32. package/ai/agent/runAgentBackground.ts +238 -0
  33. package/ai/agent/runAgentClientLoop.ts +138 -0
  34. package/ai/agent/runtimeGuidance.ts +97 -0
  35. package/ai/agent/runtimeServerBase.ts +37 -0
  36. package/ai/agent/server/fetchPublicAgents.ts +128 -0
  37. package/ai/agent/startParallelAgentStreams.ts +424 -0
  38. package/ai/agent/startupProtocol.ts +53 -0
  39. package/ai/agent/streamAgentChatTurn.ts +1299 -0
  40. package/ai/agent/streamAgentChatTurnUtils.ts +738 -0
  41. package/ai/agent/types.ts +71 -0
  42. package/ai/agent/utils/imageOutput.ts +39 -0
  43. package/ai/agent/utils/publicImageAgentMode.ts +26 -0
  44. package/ai/agent/utils/sortUtils.ts +250 -0
  45. package/ai/agent/web/referencePickerUtils.ts +146 -0
  46. package/ai/ai.locale.ts +1083 -0
  47. package/ai/chat/accumulateToolCallChunks.ts +95 -0
  48. package/ai/chat/fetchUtils.native.ts +276 -0
  49. package/ai/chat/fetchUtils.ts +153 -0
  50. package/ai/chat/inlineImageUrlsForCustomProvider.ts +117 -0
  51. package/ai/chat/parseApiError.ts +64 -0
  52. package/ai/chat/parseMultilineSSE.ts +95 -0
  53. package/ai/chat/sendOpenAICompletionsRequest.native.ts +682 -0
  54. package/ai/chat/sendOpenAICompletionsRequest.ts +712 -0
  55. package/ai/chat/sendOpenAIResponseRequest.ts +512 -0
  56. package/ai/chat/shouldUseServerProxy.ts +18 -0
  57. package/ai/chat/sseClient.native.ts +91 -0
  58. package/ai/chat/sseClient.ts +67 -0
  59. package/ai/chat/streamReader.native.ts +31 -0
  60. package/ai/chat/streamReader.ts +62 -0
  61. package/ai/chat/updateTotalUsage.ts +72 -0
  62. package/ai/context/buildReferenceContext.ts +437 -0
  63. package/ai/context/calculateContextUsage.ts +133 -0
  64. package/ai/context/retention.ts +165 -0
  65. package/ai/context/tokenUtils.ts +78 -0
  66. package/ai/index.ts +1 -1
  67. package/ai/llm/agentCapabilities.ts +74 -0
  68. package/ai/llm/calculateGeminiImageTokens.ts +57 -0
  69. package/ai/llm/deepinfra.ts +28 -0
  70. package/ai/llm/fireworks.ts +68 -0
  71. package/ai/llm/generateRequestBody.ts +165 -0
  72. package/ai/llm/getModelContextWindow.ts +84 -0
  73. package/ai/llm/getNoloKey.ts +37 -0
  74. package/ai/llm/getPricing.ts +232 -0
  75. package/ai/llm/hooks/useModelPricing.ts +75 -0
  76. package/ai/llm/imagePricing.ts +66 -0
  77. package/ai/llm/isResponseAPIModel.ts +13 -0
  78. package/ai/llm/kimi.ts +18 -0
  79. package/ai/llm/mimo.ts +71 -0
  80. package/ai/llm/mistral.ts +22 -0
  81. package/ai/llm/modelAvatar.ts +427 -0
  82. package/ai/llm/models.ts +45 -0
  83. package/ai/llm/openrouterModels.ts +141 -0
  84. package/ai/llm/providers.ts +307 -0
  85. package/ai/llm/reasoningModels.ts +28 -0
  86. package/ai/llm/types.ts +59 -0
  87. package/ai/llm/usageRequestOptions.ts +59 -0
  88. package/ai/memory/capture.ts +148 -0
  89. package/ai/memory/consolidate.ts +104 -0
  90. package/ai/memory/delete.ts +147 -0
  91. package/ai/memory/overlay.ts +84 -0
  92. package/ai/memory/query.ts +38 -0
  93. package/ai/memory/queryShared.ts +160 -0
  94. package/ai/memory/rank.ts +105 -0
  95. package/ai/memory/recentRelationshipRecap.ts +247 -0
  96. package/ai/memory/remember.ts +167 -0
  97. package/ai/memory/runtime.ts +76 -0
  98. package/ai/memory/store.ts +20 -0
  99. package/ai/memory/storeShared.ts +76 -0
  100. package/ai/memory/types.ts +46 -0
  101. package/ai/memory/understanding.ts +349 -0
  102. package/ai/memory/understandingGreeting.ts +264 -0
  103. package/ai/messages/type.ts +20 -0
  104. package/ai/policy/personalizationDialog.ts +333 -0
  105. package/ai/policy/runtimePolicy.ts +440 -0
  106. package/ai/policy/selfUpdateFields.ts +48 -0
  107. package/ai/policy/types.ts +64 -0
  108. package/ai/skills/referenceRuntime.ts +274 -0
  109. package/ai/skills/skillDiagnostics.ts +251 -0
  110. package/ai/skills/skillDocBuilder.ts +139 -0
  111. package/ai/skills/skillDocProtocol.ts +434 -0
  112. package/ai/skills/skillReferenceSummary.ts +63 -0
  113. package/ai/skills/skillSummaryMarker.ts +26 -0
  114. package/ai/token/calculatePrice.ts +546 -0
  115. package/ai/token/db.ts +98 -0
  116. package/ai/token/externalToolCost.ts +321 -0
  117. package/ai/token/hooks/useRecords.ts +65 -0
  118. package/ai/token/missingUsageEstimate.ts +42 -0
  119. package/ai/token/modelUsageQuery.ts +252 -0
  120. package/ai/token/normalizeUsage.ts +84 -0
  121. package/ai/token/openaiImageGenerationUsage.ts +56 -0
  122. package/ai/token/prepareTokenUsageData.ts +88 -0
  123. package/ai/token/query.ts +88 -0
  124. package/ai/token/queryUserTokens.ts +59 -0
  125. package/ai/token/resolveBillingTarget.ts +52 -0
  126. package/ai/token/saveTokenRecord.ts +53 -0
  127. package/ai/token/serverDialogProjection.ts +78 -0
  128. package/ai/token/serverTokenWriter.ts +143 -0
  129. package/ai/token/stats.ts +21 -0
  130. package/ai/token/tokenThunks.ts +24 -0
  131. package/ai/token/types.ts +93 -0
  132. package/ai/tools/agent/agentTools.ts +176 -0
  133. package/ai/tools/agent/agentUpdateShared.ts +311 -0
  134. package/ai/tools/agent/callAgentTool.ts +139 -0
  135. package/ai/tools/agent/createAgentTool.ts +512 -0
  136. package/ai/tools/agent/createDialogTool.ts +69 -0
  137. package/ai/tools/agent/createSkillAgentTool.ts +62 -0
  138. package/ai/tools/agent/parallelBudget.ts +221 -0
  139. package/ai/tools/agent/presets/appBuilderPreset.ts +147 -0
  140. package/ai/tools/agent/runLlmTool.ts +96 -0
  141. package/ai/tools/agent/runStreamingAgentTool.ts +73 -0
  142. package/ai/tools/agent/skillAgentArgs.ts +106 -0
  143. package/ai/tools/agent/skillAgentPreset.ts +89 -0
  144. package/ai/tools/agent/streamParallelAgentsTool.ts +122 -0
  145. package/ai/tools/agent/updateAgentTool.ts +96 -0
  146. package/ai/tools/agent/updateSelfTool.ts +113 -0
  147. package/ai/tools/amazonProductScraperTool.ts +86 -0
  148. package/ai/tools/apifyActorClient.ts +45 -0
  149. package/ai/tools/appEditGuard.ts +372 -0
  150. package/ai/tools/appReadSnapshot.ts +153 -0
  151. package/ai/tools/appTools.ts +1549 -0
  152. package/ai/tools/applyEditTool.ts +256 -0
  153. package/ai/tools/applyLineEditsTool.ts +312 -0
  154. package/ai/tools/browserTools/click.ts +33 -0
  155. package/ai/tools/browserTools/closeSession.ts +29 -0
  156. package/ai/tools/browserTools/common.ts +27 -0
  157. package/ai/tools/browserTools/openSession.ts +48 -0
  158. package/ai/tools/browserTools/readContent.ts +38 -0
  159. package/ai/tools/browserTools/selectOption.ts +46 -0
  160. package/ai/tools/browserTools/typeText.ts +42 -0
  161. package/ai/tools/category/createCategoryTool.ts +66 -0
  162. package/ai/tools/category/queryContentsByCategoryTool.ts +69 -0
  163. package/ai/tools/category/updateContentCategoryTool.ts +75 -0
  164. package/ai/tools/cfBrowserTools.ts +319 -0
  165. package/ai/tools/cfSpeechToTextTool.ts +49 -0
  166. package/ai/tools/checkEnvTool.ts +65 -0
  167. package/ai/tools/cloudflareCrawlTool.ts +289 -0
  168. package/ai/tools/codeSearchTool.ts +111 -0
  169. package/ai/tools/codeTools.ts +101 -0
  170. package/ai/tools/createDocTool.ts +132 -0
  171. package/ai/tools/createPlanTool.ts +999 -0
  172. package/ai/tools/createSkillDocTool.ts +155 -0
  173. package/ai/tools/createWorkflowTool.ts +154 -0
  174. package/ai/tools/deepseekOcrTool.ts +34 -0
  175. package/ai/tools/delayTool.ts +31 -0
  176. package/ai/tools/deleteSpacesTool.ts +325 -0
  177. package/ai/tools/deleteSpacesToolModel.ts +159 -0
  178. package/ai/tools/devReloadUtils.ts +29 -0
  179. package/ai/tools/dialogMessageSearch.ts +137 -0
  180. package/ai/tools/doctorSkillTool.ts +72 -0
  181. package/ai/tools/ecommerceScraperTool.ts +86 -0
  182. package/ai/tools/emailTools.ts +549 -0
  183. package/ai/tools/evalSkillTool.ts +92 -0
  184. package/ai/tools/exaSearchTool.ts +64 -0
  185. package/ai/tools/execBashTool.ts +379 -0
  186. package/ai/tools/executeSqlTool.ts +192 -0
  187. package/ai/tools/fetchWebpageSupport.ts +309 -0
  188. package/ai/tools/fetchWebpageTool.ts +84 -0
  189. package/ai/tools/geminiImagePreviewTool.ts +361 -0
  190. package/ai/tools/generateDocxTool.ts +215 -0
  191. package/ai/tools/googleSearchScraperTool.ts +106 -0
  192. package/ai/tools/importDataTool.ts +133 -0
  193. package/ai/tools/importSkillTool.ts +162 -0
  194. package/ai/tools/index.ts +1927 -0
  195. package/ai/tools/listFilesTool.ts +82 -0
  196. package/ai/tools/listUserSpacesTool.ts +113 -0
  197. package/ai/tools/modelUsageTools.ts +199 -0
  198. package/ai/tools/olmOcrTool.ts +34 -0
  199. package/ai/tools/openaiImageTool.ts +267 -0
  200. package/ai/tools/prepareTools.ts +23 -0
  201. package/ai/tools/readDocTool.ts +84 -0
  202. package/ai/tools/readFileTool.ts +211 -0
  203. package/ai/tools/readTool.ts +163 -0
  204. package/ai/tools/readXPostTool.ts +233 -0
  205. package/ai/tools/rememberMemoryTool.ts +84 -0
  206. package/ai/tools/remotionVideoTool.ts +151 -0
  207. package/ai/tools/searchDialogMessagesTool.ts +222 -0
  208. package/ai/tools/searchRepoTool.ts +115 -0
  209. package/ai/tools/searchWorkspaceTool.ts +259 -0
  210. package/ai/tools/skillFollowup.ts +86 -0
  211. package/ai/tools/surfWeatherTool.ts +169 -0
  212. package/ai/tools/table/addTableRowTool.ts +217 -0
  213. package/ai/tools/table/createTableTool.ts +315 -0
  214. package/ai/tools/table/rowTools.ts +366 -0
  215. package/ai/tools/table/schemaTools.ts +244 -0
  216. package/ai/tools/table/shareTableTool.ts +148 -0
  217. package/ai/tools/table/toolShared.ts +129 -0
  218. package/ai/tools/toolApiClient.ts +198 -0
  219. package/ai/tools/toolNameAliases.ts +57 -0
  220. package/ai/tools/toolResultError.ts +42 -0
  221. package/ai/tools/toolRunSlice.ts +303 -0
  222. package/ai/tools/toolSchemaCompatibility.ts +53 -0
  223. package/ai/tools/toolVisibility.ts +4 -0
  224. package/ai/tools/types.ts +20 -0
  225. package/ai/tools/uiAskChoiceTool.ts +104 -0
  226. package/ai/tools/updateContentTitleTool.ts +84 -0
  227. package/ai/tools/updateDocTool.ts +105 -0
  228. package/ai/tools/updateUserPreferenceProfileTool.ts +145 -0
  229. package/ai/tools/whisperTool.ts +77 -0
  230. package/ai/tools/writeFileTool.ts +210 -0
  231. package/ai/tools/youtubeScraperTool.ts +116 -0
  232. package/ai/tools/ziweiChartTool.ts +678 -0
  233. package/ai/types.ts +55 -0
  234. package/ai/workflow/workflowExecutor.ts +323 -0
  235. package/ai/workflow/workflowSlice.ts +73 -0
  236. package/ai/workflow/workflowTypes.ts +106 -0
  237. package/client/agentRun.test.ts +240 -0
  238. package/client/agentRun.ts +182 -19
  239. package/client/compactDialog.test.ts +238 -0
  240. package/client/localRuntimeAdapter.test.ts +135 -0
  241. package/client/localRuntimeAdapter.ts +244 -0
  242. package/client/profileConfig.test.ts +40 -0
  243. package/client/streamingOutput.test.ts +22 -0
  244. package/client/streamingOutput.ts +38 -0
  245. package/commandRegistry.ts +9 -2
  246. package/connector-experimental/index.ts +5 -0
  247. package/database/actions/cacheMergedUserData.ts +64 -0
  248. package/database/actions/common.ts +242 -0
  249. package/database/actions/deleteFile.ts +40 -0
  250. package/database/actions/fetchUserData.ts +16 -0
  251. package/database/actions/fileContent.ts +125 -0
  252. package/database/actions/patch.ts +155 -0
  253. package/database/actions/read.ts +337 -0
  254. package/database/actions/readAndWait.ts +224 -0
  255. package/database/actions/readRequestManager.ts +120 -0
  256. package/database/actions/remove.ts +94 -0
  257. package/database/actions/replication.ts +366 -0
  258. package/database/actions/upload.ts +174 -0
  259. package/database/actions/upsert.ts +56 -0
  260. package/database/actions/write.ts +126 -0
  261. package/database/client/db.native.ts +73 -0
  262. package/database/client/db.ts +51 -0
  263. package/database/client/fetchUserData.ts +61 -0
  264. package/database/client/handleError.ts +19 -0
  265. package/database/client/queryRequest.ts +21 -0
  266. package/database/config.ts +21 -0
  267. package/database/dbActionThunks.ts +1 -0
  268. package/database/dbSlice.ts +149 -0
  269. package/database/email.ts +42 -0
  270. package/database/fileRing.ts +51 -0
  271. package/database/fileSharding.ts +70 -0
  272. package/database/fileStorage.native.ts +92 -0
  273. package/database/fileStorage.ts +232 -0
  274. package/database/fileUrl.ts +34 -0
  275. package/database/hooks/useUserData.ts +489 -0
  276. package/database/index.ts +1 -0
  277. package/database/keys.ts +765 -0
  278. package/database/queryPrefixes.ts +14 -0
  279. package/database/requests.ts +443 -0
  280. package/database/runtimeServerContext.ts +35 -0
  281. package/database/server/MemoryDB.ts +76 -0
  282. package/database/server/actorAccess.ts +76 -0
  283. package/database/server/agentDelegation.ts +124 -0
  284. package/database/server/coreDataOwnership.ts +13 -0
  285. package/database/server/coreDataProxy.ts +76 -0
  286. package/database/server/cybotReadonly.ts +18 -0
  287. package/database/server/dataHandlers.ts +111 -0
  288. package/database/server/db.ts +118 -0
  289. package/database/server/dbPath.ts +20 -0
  290. package/database/server/delete.ts +499 -0
  291. package/database/server/emailRepository.ts +1480 -0
  292. package/database/server/ensureDbOpen.ts +12 -0
  293. package/database/server/fileRead.ts +337 -0
  294. package/database/server/fileService.ts +436 -0
  295. package/database/server/handleTransaction.ts +86 -0
  296. package/database/server/patch.ts +282 -0
  297. package/database/server/query.ts +138 -0
  298. package/database/server/read.ts +325 -0
  299. package/database/server/resourceAccess.ts +211 -0
  300. package/database/server/routes.ts +110 -0
  301. package/database/server/spaceMemberAuthority.ts +67 -0
  302. package/database/server/upload.ts +159 -0
  303. package/database/server/write.ts +494 -0
  304. package/database/server/writeAuthority.ts +133 -0
  305. package/database/sqliteDb.ts +46 -0
  306. package/database/table/deleteTable.ts +120 -0
  307. package/database/tenantPlacement.ts +57 -0
  308. package/database/tombstones.ts +52 -0
  309. package/database/userDataLoadDecision.ts +17 -0
  310. package/database/userDataMerge.ts +95 -0
  311. package/database/userPreferenceRegister.ts +108 -0
  312. package/database/utils/dbPath.ts +47 -0
  313. package/database/utils/ulid.native.ts +6 -0
  314. package/database/utils/ulid.ts +1 -0
  315. package/index.ts +25 -15
  316. package/localRuntimeDb.ts +28 -0
  317. package/package.json +16 -4
  318. package/runtimeModeArgs.ts +33 -0
  319. package/tui/readlineWorkspace.ts +1 -0
  320. package/tui/session.ts +22 -0
package/README.md CHANGED
@@ -93,8 +93,10 @@ nolo connect --daemon
93
93
  nolo daemon --server-url https://api.nolo.chat --api-key sk_machine_xxx
94
94
  nolo machine status
95
95
  nolo run "summarize my latest agent dialogs"
96
- nolo doc create --title "Trip Notes" --body "hello"
97
- nolo skill-doc create --title "Agent Query Skill" --description "Inspect recent agent dialogs"
96
+ nolo doc create --title "Trip Notes" --body "hello" --sync local,us --dry-run
97
+ nolo doc create --title "Proxy Notes" --description "Windows setup" --body-file ./proxy.md --sync local,main,us --allow-secrets
98
+ nolo skill-doc create --title "Agent Query Skill" --description "Inspect recent agent dialogs" --body-file ./skill.md --sync local,main,us
99
+ nolo space read 01KKY77TT0DA9NY7TNW3R7255N --content-key page-user-id --brief
98
100
  nolo agent list --json
99
101
  nolo agent bind-current agent-user-1-agent-1
100
102
  nolo agent runtime-doctor agent-user-1-agent-1
@@ -102,6 +104,11 @@ nolo agent smoke-current agent-user-1-agent-1 --msg "ping"
102
104
  nolo chat --agent agent-pub-01APPBUILDER00000001YAII3I --msg "你好"
103
105
  ```
104
106
 
107
+ For document creation, prefer the CLI over direct scripts. Use `nolo doc create`
108
+ for ordinary pages and `nolo skill-doc create` for skill-backed pages. Both
109
+ support `--sync`, `--dry-run`, `--json`, and `--allow-secrets`; scripts remain
110
+ the lower-level fallback for debugging.
111
+
105
112
  Experimental machine connector commands:
106
113
 
107
114
  ```bash
@@ -0,0 +1,53 @@
1
+ import type {
2
+ AgentRuntimeChatMessage,
3
+ AgentRuntimeHost,
4
+ AgentRuntimeResult,
5
+ } from "./types";
6
+
7
+ export type AgentRuntimeAgentConfig = {
8
+ key: string;
9
+ name?: string;
10
+ prompt?: string;
11
+ model?: string;
12
+ provider?: string;
13
+ toolNames?: string[];
14
+ };
15
+
16
+ export type AgentRuntimeProvider = {
17
+ model: string;
18
+ complete(messages: AgentRuntimeChatMessage[]): Promise<AgentRuntimeResult>;
19
+ };
20
+
21
+ export type AgentRuntimeToolCallInput = {
22
+ id: string;
23
+ name: string;
24
+ arguments: string;
25
+ };
26
+
27
+ export type AgentRuntimeToolResult = {
28
+ content: string;
29
+ metadata?: Record<string, unknown>;
30
+ };
31
+
32
+ export type AgentRuntimeSaveTurnInput = {
33
+ agentKey: string;
34
+ messages: AgentRuntimeChatMessage[];
35
+ result: AgentRuntimeResult;
36
+ };
37
+
38
+ export type AgentRuntimeHostAdapter = {
39
+ host: AgentRuntimeHost;
40
+ capabilities: string[];
41
+ loadAgentConfig(agentRef: string): Promise<AgentRuntimeAgentConfig | null>;
42
+ loadDialogHistory(dialogId: string): Promise<AgentRuntimeChatMessage[]>;
43
+ saveTurn(input: AgentRuntimeSaveTurnInput): Promise<{ dialogId: string }>;
44
+ resolveProvider(agentConfig: AgentRuntimeAgentConfig): Promise<AgentRuntimeProvider>;
45
+ executeTool(call: AgentRuntimeToolCallInput): Promise<AgentRuntimeToolResult>;
46
+ };
47
+
48
+ export function createRuntimeHostDescriptor(adapter: AgentRuntimeHostAdapter) {
49
+ return {
50
+ host: adapter.host,
51
+ capabilities: [...adapter.capabilities],
52
+ };
53
+ }
@@ -0,0 +1,28 @@
1
+ export const AGENT_RUNTIME_PACKAGE_ID = "agent-runtime";
2
+
3
+ export { createRuntimeHostDescriptor } from "./hostAdapter";
4
+ export { runLocalAgentTurn } from "./localLoop";
5
+ export { resolveAgentRuntimeDecision } from "./runtimeDecision";
6
+ export type {
7
+ AgentRuntimeAgentConfig,
8
+ AgentRuntimeHostAdapter,
9
+ AgentRuntimeProvider,
10
+ AgentRuntimeSaveTurnInput,
11
+ AgentRuntimeToolCallInput,
12
+ AgentRuntimeToolResult,
13
+ } from "./hostAdapter";
14
+ export type {
15
+ LocalAgentTurnInput,
16
+ LocalAgentTurnResult,
17
+ } from "./localLoop";
18
+ export type {
19
+ AgentRuntimeChatMessage,
20
+ AgentRuntimeDecision,
21
+ AgentRuntimeDecisionInput,
22
+ AgentRuntimeHost,
23
+ AgentRuntimeMessageContent,
24
+ AgentRuntimeMode,
25
+ AgentRuntimeRequestedMode,
26
+ AgentRuntimeResult,
27
+ AgentRuntimeToolCall,
28
+ } from "./types";
@@ -0,0 +1,62 @@
1
+ import type {
2
+ AgentRuntimeHostAdapter,
3
+ } from "./hostAdapter";
4
+ import type {
5
+ AgentRuntimeChatMessage,
6
+ AgentRuntimeResult,
7
+ } from "./types";
8
+
9
+ export type LocalAgentTurnInput = {
10
+ adapter: AgentRuntimeHostAdapter;
11
+ agentRef: string;
12
+ input: string;
13
+ continueDialogId?: string;
14
+ };
15
+
16
+ export type LocalAgentTurnResult = AgentRuntimeResult & {
17
+ dialogId: string;
18
+ };
19
+
20
+ function buildMessages(args: {
21
+ prompt?: string;
22
+ history: AgentRuntimeChatMessage[];
23
+ input: string;
24
+ }): AgentRuntimeChatMessage[] {
25
+ return [
26
+ ...(args.prompt?.trim()
27
+ ? [{ role: "system" as const, content: args.prompt.trim() }]
28
+ : []),
29
+ ...args.history,
30
+ { role: "user" as const, content: args.input },
31
+ ];
32
+ }
33
+
34
+ export async function runLocalAgentTurn(
35
+ input: LocalAgentTurnInput
36
+ ): Promise<LocalAgentTurnResult> {
37
+ const agentConfig = await input.adapter.loadAgentConfig(input.agentRef);
38
+ if (!agentConfig) {
39
+ throw new Error(`Local agent config not found: ${input.agentRef}`);
40
+ }
41
+
42
+ const history = input.continueDialogId
43
+ ? await input.adapter.loadDialogHistory(input.continueDialogId)
44
+ : [];
45
+ const messages = buildMessages({
46
+ prompt: agentConfig.prompt,
47
+ history,
48
+ input: input.input,
49
+ });
50
+ const provider = await input.adapter.resolveProvider(agentConfig);
51
+ const result = await provider.complete(messages);
52
+ const saved = await input.adapter.saveTurn({
53
+ agentKey: agentConfig.key,
54
+ messages,
55
+ result,
56
+ });
57
+
58
+ return {
59
+ ...result,
60
+ dialogId: saved.dialogId,
61
+ };
62
+ }
@@ -0,0 +1,70 @@
1
+ import type {
2
+ AgentRuntimeDecision,
3
+ AgentRuntimeDecisionInput,
4
+ } from "./types";
5
+
6
+ function uniqueCapabilities(capabilities: string[]) {
7
+ return [...new Set(capabilities.filter(Boolean))];
8
+ }
9
+
10
+ function localMissingCapabilities(input: AgentRuntimeDecisionInput) {
11
+ const missing = [...(input.missingLocalCapabilities ?? [])];
12
+ if (!input.hasLocalAgentConfig) missing.push("agent-config");
13
+ if (!input.hasLocalProvider) missing.push("provider");
14
+ if (!input.hasLocalPersistence) missing.push("persistence");
15
+ if (input.requiresServer) missing.push("server-required");
16
+ if (input.host === "web") missing.push("local-host-adapter");
17
+ return uniqueCapabilities(missing);
18
+ }
19
+
20
+ export function resolveAgentRuntimeDecision(
21
+ input: AgentRuntimeDecisionInput
22
+ ): AgentRuntimeDecision {
23
+ const requestedMode = input.requestedMode ?? "auto";
24
+ const missingLocalCapabilities = localMissingCapabilities(input);
25
+ const localRunnable = missingLocalCapabilities.length === 0;
26
+
27
+ if (requestedMode === "server") {
28
+ return {
29
+ mode: "server",
30
+ runnable: input.serverFallbackAvailable,
31
+ reason: input.serverFallbackAvailable
32
+ ? "server runtime was requested"
33
+ : "server runtime was requested but no server fallback is available",
34
+ missingLocalCapabilities,
35
+ syncAfterRun: false,
36
+ };
37
+ }
38
+
39
+ if (requestedMode === "local") {
40
+ return {
41
+ mode: "local",
42
+ runnable: localRunnable,
43
+ reason: localRunnable
44
+ ? "local runtime was requested and all local capabilities are available"
45
+ : "local runtime was requested but local capabilities are missing",
46
+ missingLocalCapabilities,
47
+ syncAfterRun: localRunnable && Boolean(input.syncRequested),
48
+ };
49
+ }
50
+
51
+ if (localRunnable) {
52
+ return {
53
+ mode: "local",
54
+ runnable: true,
55
+ reason: "local runtime capabilities are available",
56
+ missingLocalCapabilities,
57
+ syncAfterRun: Boolean(input.syncRequested),
58
+ };
59
+ }
60
+
61
+ return {
62
+ mode: "server",
63
+ runnable: input.serverFallbackAvailable,
64
+ reason: input.serverFallbackAvailable
65
+ ? "local runtime capabilities are missing; using server fallback"
66
+ : "local runtime capabilities are missing and no server fallback is available",
67
+ missingLocalCapabilities,
68
+ syncAfterRun: false,
69
+ };
70
+ }
@@ -0,0 +1,87 @@
1
+ export type AgentRuntimeMode = "local" | "server";
2
+ export type AgentRuntimeHost = "cli" | "desktop" | "web" | "server";
3
+ export type AgentRuntimeRequestedMode = "auto" | AgentRuntimeMode;
4
+
5
+ export const AGENT_RUNTIME_MESSAGE_ROLES = ["system", "user", "assistant", "tool"] as const;
6
+
7
+ export type AgentRuntimeMessageContent =
8
+ | string
9
+ | Array<
10
+ | { type: "text"; text: string }
11
+ | {
12
+ type: "image_url";
13
+ image_url: { url: string };
14
+ google_native?: {
15
+ inlineData: {
16
+ mimeType: string;
17
+ data: string;
18
+ };
19
+ thoughtSignature?: string;
20
+ };
21
+ }
22
+ >
23
+ | null;
24
+
25
+ export interface AgentRuntimeToolCall {
26
+ id: string;
27
+ type: "function";
28
+ function: { name: string; arguments: string };
29
+ }
30
+
31
+ export interface AgentRuntimeChatMessage {
32
+ role: (typeof AGENT_RUNTIME_MESSAGE_ROLES)[number];
33
+ content: AgentRuntimeMessageContent;
34
+ tool_call_id?: string;
35
+ tool_calls?: AgentRuntimeToolCall[];
36
+ reasoning_content?: string;
37
+ cybotKey?: string;
38
+ agentKey?: string;
39
+ agentName?: string;
40
+ parallelSessionId?: string;
41
+ parallelBranchId?: string;
42
+ parallelLabel?: string;
43
+ parallelIndex?: number;
44
+ }
45
+
46
+ export interface AgentRuntimeResult {
47
+ content: string;
48
+ model: string;
49
+ provider?: string;
50
+ inputPrice?: number;
51
+ outputPrice?: number;
52
+ usage?: Record<string, any>;
53
+ trace?: AgentRuntimeChatMessage[];
54
+ runtimeToolNames?: string[];
55
+ toolCallCount?: number;
56
+ policyState?: unknown;
57
+ latencyProfile?: {
58
+ totalMs: number;
59
+ llmRequestCount: number;
60
+ llmWaitMs: number;
61
+ llmJsonParseMs: number;
62
+ toolExecutionMs: number;
63
+ timeToFirstAssistantMs?: number;
64
+ timeToFirstToolResultMs?: number;
65
+ endedAt: number;
66
+ };
67
+ }
68
+
69
+ export type AgentRuntimeDecisionInput = {
70
+ requestedMode?: AgentRuntimeRequestedMode;
71
+ syncRequested?: boolean;
72
+ host?: AgentRuntimeHost;
73
+ hasLocalAgentConfig: boolean;
74
+ hasLocalProvider: boolean;
75
+ hasLocalPersistence: boolean;
76
+ missingLocalCapabilities?: string[];
77
+ requiresServer?: boolean;
78
+ serverFallbackAvailable: boolean;
79
+ };
80
+
81
+ export type AgentRuntimeDecision = {
82
+ mode: AgentRuntimeMode;
83
+ runnable: boolean;
84
+ reason: string;
85
+ missingLocalCapabilities: string[];
86
+ syncAfterRun: boolean;
87
+ };
@@ -1,8 +1,10 @@
1
- import type { MachineHeartbeat } from "./connector-experimental/protocol";
2
- import { detectMachineInfo } from "./connector-experimental/machineInfo";
3
- import {
4
- assertMachineRunAllowed,
5
- buildMachinePermissionPromptBlock,
1
+ import type { MachineHeartbeat } from "./connector-experimental/protocol";
2
+ import { detectMachineInfo } from "./connector-experimental/machineInfo";
3
+ import { resolveAgentRuntimeDecision } from "./agent-runtime/runtimeDecision";
4
+ import { resolveCliLocalRuntimeDbPath } from "./localRuntimeDb";
5
+ import {
6
+ assertMachineRunAllowed,
7
+ buildMachinePermissionPromptBlock,
6
8
  resolveMachineRunPermissionPolicy,
7
9
  } from "./ai/agent/machineRunPermissions";
8
10
  import { resolveConnectorWebSocketTarget } from "./connectorWebSocketTarget";
@@ -16,28 +18,89 @@ type SmokeWebSocketOptions = {
16
18
  onOpen: () => void | Promise<void>;
17
19
  sentMessages: string[];
18
20
  };
19
- type LocalCliExecutor = (
20
- provider: string,
21
- prompt: string,
22
- options: { model?: string; yolo?: boolean }
23
- ) => Promise<{ text: string; raw?: string; elapsed?: number }>;
24
-
25
- type AgentRuntimeCommandDeps = {
21
+ type LocalCliExecutor = (
22
+ provider: string,
23
+ prompt: string,
24
+ options: { model?: string; yolo?: boolean }
25
+ ) => Promise<{ text: string; raw?: string; elapsed?: number }>;
26
+ type LocalRuntimeProbeResult = {
27
+ ok: boolean;
28
+ dbPath: string;
29
+ agentFound: boolean;
30
+ agentKey?: string;
31
+ error?: string;
32
+ };
33
+
34
+ type AgentRuntimeCommandDeps = {
26
35
  env?: EnvLike;
27
36
  output?: OutputLike;
28
37
  fetchImpl?: typeof fetch;
29
- machineInfo?: () => MachineHeartbeat;
30
- connectWebSocket?: (url: string, options: SmokeWebSocketOptions) => Promise<void>;
31
- executeCli?: LocalCliExecutor;
32
- };
38
+ machineInfo?: () => MachineHeartbeat;
39
+ connectWebSocket?: (url: string, options: SmokeWebSocketOptions) => Promise<void>;
40
+ executeCli?: LocalCliExecutor;
41
+ localRuntimeProbe?: (env: EnvLike) => Promise<LocalRuntimeProbeResult>;
42
+ };
33
43
 
34
44
  function resolveServerUrl(env: EnvLike) {
35
45
  return (env.NOLO_SERVER || env.BASE_URL || DEFAULT_NOLO_SERVER_URL).replace(/\/+$/, "");
36
46
  }
37
47
 
38
- function resolveAuthToken(env: EnvLike) {
39
- return env.AUTH_TOKEN || env.AUTH || "";
40
- }
48
+ function resolveAuthToken(env: EnvLike) {
49
+ return env.AUTH_TOKEN || env.AUTH || "";
50
+ }
51
+
52
+ function detectLocalAgentConfig(env: EnvLike) {
53
+ return Boolean(readLocalAgentKey(env) || env.NOLO_AGENT_CACHE_READY);
54
+ }
55
+
56
+ function readLocalAgentKey(env: EnvLike) {
57
+ return env.NOLO_LOCAL_AGENT_KEY || env.NOLO_AGENT || "";
58
+ }
59
+
60
+ function detectLocalProvider(env: EnvLike) {
61
+ return Boolean(
62
+ env.OPENAI_API_KEY ||
63
+ env.ANTHROPIC_API_KEY ||
64
+ env.GOOGLE_API_KEY ||
65
+ env.NOLO_LOCAL_OPENAI_BASE_URL ||
66
+ env.OLLAMA_BASE_URL
67
+ );
68
+ }
69
+
70
+ function detectProviderLabel(env: EnvLike) {
71
+ if (env.NOLO_LOCAL_OPENAI_BASE_URL) return `openai-compatible endpoint ${env.NOLO_LOCAL_OPENAI_BASE_URL}`;
72
+ if (env.OLLAMA_BASE_URL) return `ollama-compatible endpoint ${env.OLLAMA_BASE_URL}`;
73
+ if (env.OPENAI_API_KEY) return "openai via env OPENAI_API_KEY";
74
+ if (env.ANTHROPIC_API_KEY) return "anthropic via env ANTHROPIC_API_KEY";
75
+ if (env.GOOGLE_API_KEY) return "google via env GOOGLE_API_KEY";
76
+ return "missing";
77
+ }
78
+
79
+ async function defaultLocalRuntimeProbe(env: EnvLike): Promise<LocalRuntimeProbeResult> {
80
+ const dbPath = resolveCliLocalRuntimeDbPath({ env });
81
+ const agentKey = readLocalAgentKey(env);
82
+ try {
83
+ const { getDefaultCliLocalRuntimeDb } = await import("./localRuntimeDb");
84
+ const db = await getDefaultCliLocalRuntimeDb();
85
+ if (!agentKey) {
86
+ return { ok: true, dbPath, agentFound: false };
87
+ }
88
+ try {
89
+ await db.get(agentKey);
90
+ return { ok: true, dbPath, agentFound: true, agentKey };
91
+ } catch {
92
+ return { ok: true, dbPath, agentFound: false, agentKey };
93
+ }
94
+ } catch (error) {
95
+ return {
96
+ ok: false,
97
+ dbPath,
98
+ agentFound: false,
99
+ ...(agentKey ? { agentKey } : {}),
100
+ error: error instanceof Error ? error.message : String(error),
101
+ };
102
+ }
103
+ }
41
104
 
42
105
  function parseUserIdFromAuthToken(token: string) {
43
106
  const payload = token.trim().split(".")[0];
@@ -413,7 +476,7 @@ export async function runAgentSmokeCurrentCommand(
413
476
  }
414
477
  }
415
478
 
416
- export async function runAgentRuntimeDoctorCommand(
479
+ export async function runAgentRuntimeDoctorCommand(
417
480
  args: string[],
418
481
  deps: AgentRuntimeCommandDeps = {}
419
482
  ) {
@@ -462,5 +525,59 @@ export async function runAgentRuntimeDoctorCommand(
462
525
  }\n`
463
526
  );
464
527
  return 1;
465
- }
466
- }
528
+ }
529
+ }
530
+
531
+ export async function runDoctorRuntimeCommand(
532
+ _args: string[],
533
+ deps: AgentRuntimeCommandDeps = {}
534
+ ) {
535
+ const env = deps.env ?? process.env;
536
+ const output = deps.output ?? process.stdout;
537
+ const authToken = resolveAuthToken(env);
538
+ const serverUrl = resolveServerUrl(env);
539
+ const localProbe = await (deps.localRuntimeProbe ?? defaultLocalRuntimeProbe)(env);
540
+ const hasLocalAgentConfig = detectLocalAgentConfig(env) && localProbe.ok && localProbe.agentFound;
541
+ const hasLocalProvider = detectLocalProvider(env);
542
+ const missingLocalCapabilities = [
543
+ ...(localProbe.ok ? [] : ["leveldb"]),
544
+ ...(hasLocalAgentConfig ? [] : ["agent-config"]),
545
+ ...(hasLocalProvider ? [] : ["provider"]),
546
+ ];
547
+ const decision = resolveAgentRuntimeDecision({
548
+ requestedMode: "auto",
549
+ syncRequested: false,
550
+ host: "cli",
551
+ hasLocalAgentConfig,
552
+ hasLocalProvider,
553
+ hasLocalPersistence: true,
554
+ missingLocalCapabilities,
555
+ requiresServer: false,
556
+ serverFallbackAvailable: Boolean(authToken || env.NOLO_SERVER || env.BASE_URL),
557
+ });
558
+
559
+ output.write(`Runtime: ${decision.mode}\n`);
560
+ output.write(`Reason: ${decision.reason}\n`);
561
+ output.write(`LevelDB: ${localProbe.ok ? "ok" : "failed"}\n`);
562
+ output.write(`DB path: ${localProbe.dbPath}\n`);
563
+ if (!localProbe.ok && localProbe.error) {
564
+ output.write(`DB error: ${localProbe.error}\n`);
565
+ }
566
+ if (localProbe.agentKey) {
567
+ output.write(`Agent config: ${localProbe.agentFound ? "found" : "missing"} (${localProbe.agentKey})\n`);
568
+ } else {
569
+ output.write("Agent config: missing (no local agent key)\n");
570
+ }
571
+ output.write(`Provider: ${hasLocalProvider ? "available" : "missing"} (${detectProviderLabel(env)})\n`);
572
+ output.write("Persistence: LevelDB local store\n");
573
+ output.write(`Sync: ${authToken ? "available" : "unavailable"}${authToken ? "" : " (not authenticated)"}\n`);
574
+ output.write(`Server fallback: ${decision.runnable && decision.mode === "server" ? serverUrl : authToken || env.NOLO_SERVER || env.BASE_URL ? serverUrl : "unavailable"}\n`);
575
+ if (decision.missingLocalCapabilities.length > 0) {
576
+ output.write("Missing local capabilities:\n");
577
+ for (const capability of decision.missingLocalCapabilities) {
578
+ output.write(`- ${capability}\n`);
579
+ }
580
+ }
581
+
582
+ return decision.runnable ? 0 : 1;
583
+ }
@@ -0,0 +1,7 @@
1
+ export { runLocalAgentTurn } from "./agent-runtime/localLoop";
2
+ export type {
3
+ AgentRuntimeAgentConfig,
4
+ AgentRuntimeHostAdapter,
5
+ AgentRuntimeRequestedMode,
6
+ AgentRuntimeSaveTurnInput,
7
+ } from "./agent-runtime";
@@ -0,0 +1,118 @@
1
+ import { RootState } from "app/store";
2
+ import { Agent, Message } from "app/types";
3
+ import { selectCurrentDialogConfig } from "chat/dialog/dialogSlice";
4
+ import { read } from "database/dbSlice";
5
+ import { fetchAgentContexts } from "ai/agent/fetchAgentContexts";
6
+ import { filterAndCleanMessages } from "integrations/openai/filterAndCleanMessages";
7
+ import { selectAllMsgs } from "chat/messages/messageSlice";
8
+ import { generateRequestBody } from "ai/llm/generateRequestBody";
9
+ import { getApiEndpoint } from "ai/llm/providers";
10
+ import { selectCurrentServer } from "app/settings/settingSlice";
11
+ import { selectCurrentToken } from "auth/authSlice";
12
+
13
+ import { sendOpenAICompletionsRequest } from "../chat/sendOpenAICompletionsRequest";
14
+ import { performFetchRequest } from "../chat/fetchUtils";
15
+ import { updateTokensAction } from "chat/dialog/actions/updateTokensAction";
16
+ import { extractCustomId } from "core/prefix";
17
+
18
+ export const _executeModel = async (
19
+ options: {
20
+ isStreaming: boolean;
21
+ withAgentContext: boolean;
22
+ withChatHistory: boolean;
23
+ agentConfigOverrides?: Record<string, any>;
24
+ },
25
+ args: {
26
+ llmConfig?: Partial<Agent> & Pick<Agent, "provider" | "model">;
27
+ agentKey?: string;
28
+ agentConfig?: Partial<Agent> & Pick<Agent, "provider" | "model">;
29
+ content: any;
30
+ parentMessageId?: string;
31
+ billingDialogKey?: string;
32
+ },
33
+ thunkApi: any
34
+ ) => {
35
+ const { isStreaming, withAgentContext, withChatHistory, agentConfigOverrides } = options;
36
+ const { getState, dispatch, rejectWithValue } = thunkApi;
37
+ const { content } = args;
38
+ const state = getState() as RootState;
39
+
40
+ let agentConfig: Partial<Agent> & Pick<Agent, "provider" | "model">;
41
+ if (args.llmConfig) {
42
+ agentConfig = args.llmConfig;
43
+ } else if (args.agentConfig) {
44
+ agentConfig = args.agentConfig;
45
+ } else {
46
+ const agentKey = args.agentKey || selectCurrentDialogConfig(state)?.cybots?.[0];
47
+ if (!agentKey) {
48
+ const msg = "Model execution failed: No llmConfig, agentConfig, or agentKey provided.";
49
+ console.error(msg);
50
+ return rejectWithValue(msg);
51
+ }
52
+ try {
53
+ agentConfig = await dispatch(read({ dbKey: agentKey })).unwrap();
54
+ } catch (error: any) {
55
+ console.error(`_executeModel failed to load agent [${agentKey}]`, error);
56
+ return rejectWithValue(error.message);
57
+ }
58
+ }
59
+
60
+ try {
61
+ const resolvedConfig = agentConfigOverrides
62
+ ? { ...agentConfig, ...agentConfigOverrides }
63
+ : agentConfig;
64
+ const agentContexts = withAgentContext
65
+ ? await fetchAgentContexts(resolvedConfig.references, dispatch)
66
+ : {};
67
+
68
+ let messages: Message[];
69
+ if (withChatHistory) {
70
+ messages = filterAndCleanMessages(selectAllMsgs(state));
71
+ messages.push({ role: "user", content: args.content });
72
+ } else {
73
+ messages = [{ role: "user", content: args.content }];
74
+ }
75
+
76
+ const bodyData = generateRequestBody({
77
+ agentConfig: resolvedConfig,
78
+ messages,
79
+ userInput: content,
80
+ contexts: agentContexts,
81
+ });
82
+ bodyData.stream = isStreaming;
83
+
84
+ if (isStreaming) {
85
+ await sendOpenAICompletionsRequest({
86
+ bodyData,
87
+ agentConfig: resolvedConfig,
88
+ thunkApi,
89
+ dialogKey: selectCurrentDialogConfig(state)?.dbKey,
90
+ parentMessageId: args.parentMessageId,
91
+ });
92
+ } else {
93
+ const response = await performFetchRequest({
94
+ agentConfig: resolvedConfig,
95
+ api: getApiEndpoint(resolvedConfig),
96
+ bodyData,
97
+ currentServer: selectCurrentServer(state),
98
+ token: selectCurrentToken(state),
99
+ });
100
+ const result = await response.json();
101
+ if (args.billingDialogKey && result?.usage) {
102
+ await updateTokensAction(
103
+ {
104
+ dialogId: extractCustomId(args.billingDialogKey),
105
+ dialogKey: args.billingDialogKey,
106
+ usage: result.usage,
107
+ agentConfig: resolvedConfig,
108
+ },
109
+ thunkApi
110
+ );
111
+ }
112
+ return result.choices[0].message.content;
113
+ }
114
+ } catch (error: any) {
115
+ console.error(`_executeModel failed`, error);
116
+ return rejectWithValue(error.message);
117
+ }
118
+ };