nolo-cli 0.1.12 → 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 (323) hide show
  1. package/README.md +54 -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 +141 -22
  8. package/agentRuntimeLocal.ts +7 -0
  9. package/ai/agent/_executeModel.ts +118 -0
  10. package/ai/agent/agentSlice.ts +545 -0
  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/agent.ts +2 -0
  47. package/ai/ai.locale.ts +1083 -0
  48. package/ai/chat/accumulateToolCallChunks.ts +95 -0
  49. package/ai/chat/fetchUtils.native.ts +276 -0
  50. package/ai/chat/fetchUtils.ts +153 -0
  51. package/ai/chat/inlineImageUrlsForCustomProvider.ts +117 -0
  52. package/ai/chat/parseApiError.ts +64 -0
  53. package/ai/chat/parseMultilineSSE.ts +95 -0
  54. package/ai/chat/sendOpenAICompletionsRequest.native.ts +682 -0
  55. package/ai/chat/sendOpenAICompletionsRequest.ts +712 -0
  56. package/ai/chat/sendOpenAIResponseRequest.ts +512 -0
  57. package/ai/chat/shouldUseServerProxy.ts +18 -0
  58. package/ai/chat/sseClient.native.ts +91 -0
  59. package/ai/chat/sseClient.ts +67 -0
  60. package/ai/chat/streamReader.native.ts +31 -0
  61. package/ai/chat/streamReader.ts +62 -0
  62. package/ai/chat/updateTotalUsage.ts +72 -0
  63. package/ai/context/buildReferenceContext.ts +437 -0
  64. package/ai/context/calculateContextUsage.ts +133 -0
  65. package/ai/context/retention.ts +165 -0
  66. package/ai/context/tokenUtils.ts +78 -0
  67. package/ai/index.ts +1 -0
  68. package/ai/llm/agentCapabilities.ts +74 -0
  69. package/ai/llm/calculateGeminiImageTokens.ts +57 -0
  70. package/ai/llm/deepinfra.ts +28 -0
  71. package/ai/llm/fireworks.ts +68 -0
  72. package/ai/llm/generateRequestBody.ts +165 -0
  73. package/ai/llm/getModelContextWindow.ts +84 -0
  74. package/ai/llm/getNoloKey.ts +37 -0
  75. package/ai/llm/getPricing.ts +232 -0
  76. package/ai/llm/hooks/useModelPricing.ts +75 -0
  77. package/ai/llm/imagePricing.ts +66 -0
  78. package/ai/llm/isResponseAPIModel.ts +13 -0
  79. package/ai/llm/kimi.ts +18 -0
  80. package/ai/llm/mimo.ts +71 -0
  81. package/ai/llm/mistral.ts +22 -0
  82. package/ai/llm/modelAvatar.ts +427 -0
  83. package/ai/llm/models.ts +45 -0
  84. package/ai/llm/openrouterModels.ts +141 -0
  85. package/ai/llm/providers.ts +307 -0
  86. package/ai/llm/reasoningModels.ts +28 -0
  87. package/ai/llm/types.ts +59 -0
  88. package/ai/llm/usageRequestOptions.ts +59 -0
  89. package/ai/memory/capture.ts +148 -0
  90. package/ai/memory/consolidate.ts +104 -0
  91. package/ai/memory/delete.ts +147 -0
  92. package/ai/memory/overlay.ts +84 -0
  93. package/ai/memory/query.ts +38 -0
  94. package/ai/memory/queryShared.ts +160 -0
  95. package/ai/memory/rank.ts +105 -0
  96. package/ai/memory/recentRelationshipRecap.ts +247 -0
  97. package/ai/memory/remember.ts +167 -0
  98. package/ai/memory/runtime.ts +76 -0
  99. package/ai/memory/store.ts +20 -0
  100. package/ai/memory/storeShared.ts +76 -0
  101. package/ai/memory/types.ts +46 -0
  102. package/ai/memory/understanding.ts +349 -0
  103. package/ai/memory/understandingGreeting.ts +264 -0
  104. package/ai/messages/type.ts +20 -0
  105. package/ai/policy/personalizationDialog.ts +333 -0
  106. package/ai/policy/runtimePolicy.ts +440 -0
  107. package/ai/policy/selfUpdateFields.ts +48 -0
  108. package/ai/policy/types.ts +64 -0
  109. package/ai/skills/referenceRuntime.ts +274 -0
  110. package/ai/skills/skillDiagnostics.ts +251 -0
  111. package/ai/skills/skillDocBuilder.ts +139 -0
  112. package/ai/skills/skillDocProtocol.ts +434 -0
  113. package/ai/skills/skillReferenceSummary.ts +63 -0
  114. package/ai/skills/skillSummaryMarker.ts +26 -0
  115. package/ai/token/calculatePrice.ts +546 -0
  116. package/ai/token/db.ts +98 -0
  117. package/ai/token/externalToolCost.ts +321 -0
  118. package/ai/token/hooks/useRecords.ts +65 -0
  119. package/ai/token/missingUsageEstimate.ts +42 -0
  120. package/ai/token/modelUsageQuery.ts +252 -0
  121. package/ai/token/normalizeUsage.ts +84 -0
  122. package/ai/token/openaiImageGenerationUsage.ts +56 -0
  123. package/ai/token/prepareTokenUsageData.ts +88 -0
  124. package/ai/token/query.ts +88 -0
  125. package/ai/token/queryUserTokens.ts +59 -0
  126. package/ai/token/resolveBillingTarget.ts +52 -0
  127. package/ai/token/saveTokenRecord.ts +53 -0
  128. package/ai/token/serverDialogProjection.ts +78 -0
  129. package/ai/token/serverTokenWriter.ts +143 -0
  130. package/ai/token/stats.ts +21 -0
  131. package/ai/token/tokenThunks.ts +24 -0
  132. package/ai/token/types.ts +93 -0
  133. package/ai/tools/agent/agentTools.ts +176 -0
  134. package/ai/tools/agent/agentUpdateShared.ts +311 -0
  135. package/ai/tools/agent/callAgentTool.ts +139 -0
  136. package/ai/tools/agent/createAgentTool.ts +512 -0
  137. package/ai/tools/agent/createDialogTool.ts +69 -0
  138. package/ai/tools/agent/createSkillAgentTool.ts +62 -0
  139. package/ai/tools/agent/parallelBudget.ts +221 -0
  140. package/ai/tools/agent/presets/appBuilderPreset.ts +147 -0
  141. package/ai/tools/agent/runLlmTool.ts +96 -0
  142. package/ai/tools/agent/runStreamingAgentTool.ts +73 -0
  143. package/ai/tools/agent/skillAgentArgs.ts +106 -0
  144. package/ai/tools/agent/skillAgentPreset.ts +89 -0
  145. package/ai/tools/agent/streamParallelAgentsTool.ts +122 -0
  146. package/ai/tools/agent/updateAgentTool.ts +96 -0
  147. package/ai/tools/agent/updateSelfTool.ts +113 -0
  148. package/ai/tools/amazonProductScraperTool.ts +86 -0
  149. package/ai/tools/apifyActorClient.ts +45 -0
  150. package/ai/tools/appEditGuard.ts +372 -0
  151. package/ai/tools/appReadSnapshot.ts +153 -0
  152. package/ai/tools/appTools.ts +1549 -0
  153. package/ai/tools/applyEditTool.ts +256 -0
  154. package/ai/tools/applyLineEditsTool.ts +312 -0
  155. package/ai/tools/browserTools/click.ts +33 -0
  156. package/ai/tools/browserTools/closeSession.ts +29 -0
  157. package/ai/tools/browserTools/common.ts +27 -0
  158. package/ai/tools/browserTools/openSession.ts +48 -0
  159. package/ai/tools/browserTools/readContent.ts +38 -0
  160. package/ai/tools/browserTools/selectOption.ts +46 -0
  161. package/ai/tools/browserTools/typeText.ts +42 -0
  162. package/ai/tools/category/createCategoryTool.ts +66 -0
  163. package/ai/tools/category/queryContentsByCategoryTool.ts +69 -0
  164. package/ai/tools/category/updateContentCategoryTool.ts +75 -0
  165. package/ai/tools/cfBrowserTools.ts +319 -0
  166. package/ai/tools/cfSpeechToTextTool.ts +49 -0
  167. package/ai/tools/checkEnvTool.ts +65 -0
  168. package/ai/tools/cloudflareCrawlTool.ts +289 -0
  169. package/ai/tools/codeSearchTool.ts +111 -0
  170. package/ai/tools/codeTools.ts +101 -0
  171. package/ai/tools/createDocTool.ts +132 -0
  172. package/ai/tools/createPlanTool.ts +999 -0
  173. package/ai/tools/createSkillDocTool.ts +155 -0
  174. package/ai/tools/createWorkflowTool.ts +154 -0
  175. package/ai/tools/deepseekOcrTool.ts +34 -0
  176. package/ai/tools/delayTool.ts +31 -0
  177. package/ai/tools/deleteSpacesTool.ts +325 -0
  178. package/ai/tools/deleteSpacesToolModel.ts +159 -0
  179. package/ai/tools/devReloadUtils.ts +29 -0
  180. package/ai/tools/dialogMessageSearch.ts +137 -0
  181. package/ai/tools/doctorSkillTool.ts +72 -0
  182. package/ai/tools/ecommerceScraperTool.ts +86 -0
  183. package/ai/tools/emailTools.ts +549 -0
  184. package/ai/tools/evalSkillTool.ts +92 -0
  185. package/ai/tools/exaSearchTool.ts +64 -0
  186. package/ai/tools/execBashTool.ts +379 -0
  187. package/ai/tools/executeSqlTool.ts +192 -0
  188. package/ai/tools/fetchWebpageSupport.ts +309 -0
  189. package/ai/tools/fetchWebpageTool.ts +84 -0
  190. package/ai/tools/geminiImagePreviewTool.ts +361 -0
  191. package/ai/tools/generateDocxTool.ts +215 -0
  192. package/ai/tools/googleSearchScraperTool.ts +106 -0
  193. package/ai/tools/importDataTool.ts +133 -0
  194. package/ai/tools/importSkillTool.ts +162 -0
  195. package/ai/tools/index.ts +1927 -0
  196. package/ai/tools/listFilesTool.ts +82 -0
  197. package/ai/tools/listUserSpacesTool.ts +113 -0
  198. package/ai/tools/modelUsageTools.ts +199 -0
  199. package/ai/tools/olmOcrTool.ts +34 -0
  200. package/ai/tools/openaiImageTool.ts +267 -0
  201. package/ai/tools/prepareTools.ts +23 -0
  202. package/ai/tools/readDocTool.ts +84 -0
  203. package/ai/tools/readFileTool.ts +211 -0
  204. package/ai/tools/readTool.ts +163 -0
  205. package/ai/tools/readXPostTool.ts +233 -0
  206. package/ai/tools/rememberMemoryTool.ts +84 -0
  207. package/ai/tools/remotionVideoTool.ts +151 -0
  208. package/ai/tools/searchDialogMessagesTool.ts +222 -0
  209. package/ai/tools/searchRepoTool.ts +115 -0
  210. package/ai/tools/searchWorkspaceTool.ts +259 -0
  211. package/ai/tools/skillFollowup.ts +86 -0
  212. package/ai/tools/surfWeatherTool.ts +169 -0
  213. package/ai/tools/table/addTableRowTool.ts +217 -0
  214. package/ai/tools/table/createTableTool.ts +315 -0
  215. package/ai/tools/table/rowTools.ts +366 -0
  216. package/ai/tools/table/schemaTools.ts +244 -0
  217. package/ai/tools/table/shareTableTool.ts +148 -0
  218. package/ai/tools/table/toolShared.ts +129 -0
  219. package/ai/tools/toolApiClient.ts +198 -0
  220. package/ai/tools/toolNameAliases.ts +57 -0
  221. package/ai/tools/toolResultError.ts +42 -0
  222. package/ai/tools/toolRunSlice.ts +303 -0
  223. package/ai/tools/toolSchemaCompatibility.ts +53 -0
  224. package/ai/tools/toolVisibility.ts +4 -0
  225. package/ai/tools/types.ts +20 -0
  226. package/ai/tools/uiAskChoiceTool.ts +104 -0
  227. package/ai/tools/updateContentTitleTool.ts +84 -0
  228. package/ai/tools/updateDocTool.ts +105 -0
  229. package/ai/tools/updateUserPreferenceProfileTool.ts +145 -0
  230. package/ai/tools/whisperTool.ts +77 -0
  231. package/ai/tools/writeFileTool.ts +210 -0
  232. package/ai/tools/youtubeScraperTool.ts +116 -0
  233. package/ai/tools/ziweiChartTool.ts +678 -0
  234. package/ai/types.ts +55 -0
  235. package/ai/workflow/workflowExecutor.ts +323 -0
  236. package/ai/workflow/workflowSlice.ts +73 -0
  237. package/ai/workflow/workflowTypes.ts +106 -0
  238. package/authCommands.ts +185 -21
  239. package/client/agentRun.test.ts +240 -0
  240. package/client/agentRun.ts +182 -19
  241. package/client/compactDialog.test.ts +238 -0
  242. package/client/compactDialog.ts +5 -2
  243. package/client/localRuntimeAdapter.test.ts +135 -0
  244. package/client/localRuntimeAdapter.ts +244 -0
  245. package/client/profileConfig.test.ts +40 -0
  246. package/client/streamingOutput.test.ts +22 -0
  247. package/client/streamingOutput.ts +38 -0
  248. package/commandRegistry.ts +11 -2
  249. package/connector-experimental/index.ts +5 -0
  250. package/database/actions/cacheMergedUserData.ts +64 -0
  251. package/database/actions/common.ts +242 -0
  252. package/database/actions/deleteFile.ts +40 -0
  253. package/database/actions/fetchUserData.ts +16 -0
  254. package/database/actions/fileContent.ts +125 -0
  255. package/database/actions/patch.ts +155 -0
  256. package/database/actions/read.ts +337 -0
  257. package/database/actions/readAndWait.ts +224 -0
  258. package/database/actions/readRequestManager.ts +120 -0
  259. package/database/actions/remove.ts +94 -0
  260. package/database/actions/replication.ts +366 -0
  261. package/database/actions/upload.ts +174 -0
  262. package/database/actions/upsert.ts +56 -0
  263. package/database/actions/write.ts +126 -0
  264. package/database/client/db.native.ts +73 -0
  265. package/database/client/db.ts +51 -0
  266. package/database/client/fetchUserData.ts +61 -0
  267. package/database/client/handleError.ts +19 -0
  268. package/database/client/queryRequest.ts +21 -0
  269. package/database/config.ts +21 -0
  270. package/database/dbActionThunks.ts +1 -0
  271. package/database/dbSlice.ts +149 -0
  272. package/database/email.ts +42 -0
  273. package/database/fileRing.ts +51 -0
  274. package/database/fileSharding.ts +70 -0
  275. package/database/fileStorage.native.ts +92 -0
  276. package/database/fileStorage.ts +232 -0
  277. package/database/fileUrl.ts +34 -0
  278. package/database/hooks/useUserData.ts +489 -0
  279. package/database/index.ts +1 -0
  280. package/database/keys.ts +765 -0
  281. package/database/queryPrefixes.ts +14 -0
  282. package/database/requests.ts +443 -0
  283. package/database/runtimeServerContext.ts +35 -0
  284. package/database/server/MemoryDB.ts +76 -0
  285. package/database/server/actorAccess.ts +76 -0
  286. package/database/server/agentDelegation.ts +124 -0
  287. package/database/server/coreDataOwnership.ts +13 -0
  288. package/database/server/coreDataProxy.ts +76 -0
  289. package/database/server/cybotReadonly.ts +18 -0
  290. package/database/server/dataHandlers.ts +111 -0
  291. package/database/server/db.ts +118 -0
  292. package/database/server/dbPath.ts +20 -0
  293. package/database/server/delete.ts +499 -0
  294. package/database/server/emailRepository.ts +1480 -0
  295. package/database/server/ensureDbOpen.ts +12 -0
  296. package/database/server/fileRead.ts +337 -0
  297. package/database/server/fileService.ts +436 -0
  298. package/database/server/handleTransaction.ts +86 -0
  299. package/database/server/patch.ts +282 -0
  300. package/database/server/query.ts +138 -0
  301. package/database/server/read.ts +325 -0
  302. package/database/server/resourceAccess.ts +211 -0
  303. package/database/server/routes.ts +110 -0
  304. package/database/server/spaceMemberAuthority.ts +67 -0
  305. package/database/server/upload.ts +159 -0
  306. package/database/server/write.ts +494 -0
  307. package/database/server/writeAuthority.ts +133 -0
  308. package/database/sqliteDb.ts +46 -0
  309. package/database/table/deleteTable.ts +120 -0
  310. package/database/tenantPlacement.ts +57 -0
  311. package/database/tombstones.ts +52 -0
  312. package/database/userDataLoadDecision.ts +17 -0
  313. package/database/userDataMerge.ts +95 -0
  314. package/database/userPreferenceRegister.ts +108 -0
  315. package/database/utils/dbPath.ts +47 -0
  316. package/database/utils/ulid.native.ts +6 -0
  317. package/database/utils/ulid.ts +1 -0
  318. package/index.ts +25 -15
  319. package/localRuntimeDb.ts +28 -0
  320. package/package.json +16 -4
  321. package/runtimeModeArgs.ts +33 -0
  322. package/tui/readlineWorkspace.ts +1 -0
  323. package/tui/session.ts +22 -0
package/README.md CHANGED
@@ -62,6 +62,20 @@ nolo whoami
62
62
  nolo
63
63
  ```
64
64
 
65
+ By default, `nolo login` opens the Nolo website and waits for browser
66
+ authorization. In SSH or browserless environments, use:
67
+
68
+ ```bash
69
+ nolo login --no-browser
70
+ ```
71
+
72
+ Then open the printed URL on a logged-in browser. Automation can still save a
73
+ token directly:
74
+
75
+ ```bash
76
+ nolo login --server https://nolo.chat --token <token>
77
+ ```
78
+
65
79
  Local repo development can still use the script bridge without `AUTH_TOKEN`.
66
80
 
67
81
  Inside the TUI, `/update` is the shortcut for the same global `nolo update`
@@ -79,8 +93,10 @@ nolo connect --daemon
79
93
  nolo daemon --server-url https://api.nolo.chat --api-key sk_machine_xxx
80
94
  nolo machine status
81
95
  nolo run "summarize my latest agent dialogs"
82
- nolo doc create --title "Trip Notes" --body "hello"
83
- 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
84
100
  nolo agent list --json
85
101
  nolo agent bind-current agent-user-1-agent-1
86
102
  nolo agent runtime-doctor agent-user-1-agent-1
@@ -88,6 +104,11 @@ nolo agent smoke-current agent-user-1-agent-1 --msg "ping"
88
104
  nolo chat --agent agent-pub-01APPBUILDER00000001YAII3I --msg "你好"
89
105
  ```
90
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
+
91
112
  Experimental machine connector commands:
92
113
 
93
114
  ```bash
@@ -171,3 +192,34 @@ Future product-direction examples for the broader TUI command model:
171
192
 
172
193
  See [`docs/nolo-cli-tui.md`](../../docs/nolo-cli-tui.md) for the product and
173
194
  technical direction.
195
+
196
+ ## Building for Publish
197
+
198
+ The CLI is developed in a monorepo with workspace dependencies (`ai` and
199
+ `connector-experimental`). To generate a publish-safe package that can be
200
+ installed via npm outside the monorepo:
201
+
202
+ ```bash
203
+ bun run build:publish
204
+ ```
205
+
206
+ This creates a `dist/` directory with:
207
+ - All source files from the `files` array in package.json
208
+ - Inlined workspace dependencies (copied as nested directories)
209
+ - A modified package.json with workspace dependencies stripped
210
+
211
+ The `dist/` directory can be published to npm:
212
+
213
+ ```bash
214
+ cd dist
215
+ npm publish
216
+ ```
217
+
218
+ Key differences between repo-local and published versions:
219
+ - **Repo-local**: Runs from source (`packages/cli/index.ts`) with workspace
220
+ dependencies resolved by the monorepo
221
+ - **Published**: Runs from dist (`dist/index.ts`) with workspace dependencies
222
+ inlined as nested directories
223
+
224
+ Both versions use the same Bun runtime and TypeScript source files. The build
225
+ process does not transpile; it only restructures the package for standalone use.
@@ -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];
@@ -286,6 +349,7 @@ export async function runAgentBindCurrentCommand(
286
349
  ? existing.runtimeBinding
287
350
  : {}),
288
351
  machineId: machine.machineId,
352
+ ownerUserId: userId,
289
353
  },
290
354
  updatedAt: Date.now(),
291
355
  };
@@ -356,6 +420,7 @@ export async function runAgentSmokeCurrentCommand(
356
420
  ? existing.runtimeBinding
357
421
  : {}),
358
422
  machineId: machine.machineId,
423
+ ownerUserId: userId,
359
424
  },
360
425
  updatedAt: Date.now(),
361
426
  },
@@ -411,7 +476,7 @@ export async function runAgentSmokeCurrentCommand(
411
476
  }
412
477
  }
413
478
 
414
- export async function runAgentRuntimeDoctorCommand(
479
+ export async function runAgentRuntimeDoctorCommand(
415
480
  args: string[],
416
481
  deps: AgentRuntimeCommandDeps = {}
417
482
  ) {
@@ -460,5 +525,59 @@ export async function runAgentRuntimeDoctorCommand(
460
525
  }\n`
461
526
  );
462
527
  return 1;
463
- }
464
- }
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";