nolo-cli 0.1.30 → 0.1.31

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 (308) hide show
  1. package/agent-runtime/agentRecordConfig.ts +0 -2
  2. package/agent-runtime/hostAdapter.ts +0 -1
  3. package/agent-runtime/hostRuntimeCapabilities.ts +7 -0
  4. package/agent-runtime/hostRuntimeConfig.ts +86 -0
  5. package/agent-runtime/index.ts +13 -0
  6. package/agent-runtime/localToolPolicy.ts +13 -6
  7. package/agent-runtime/localWorkspaceTools.ts +333 -30
  8. package/agent-runtime/platformChatProvider.ts +4 -1
  9. package/agent-runtime/runtimeToolPolicy.ts +32 -47
  10. package/agent-runtime/shellCommandPolicy.ts +117 -0
  11. package/agent-runtime/toolGate.ts +38 -0
  12. package/agentRecordCommands.ts +1 -1
  13. package/agentRecordHelpers.ts +35 -20
  14. package/agentRunParsing.ts +18 -5
  15. package/agentRuntimeLocal.ts +10 -0
  16. package/ai/agent/agentRunDialogLineage.ts +56 -0
  17. package/ai/agent/agentSlice.ts +45 -10
  18. package/ai/agent/avatarUtils.ts +1 -1
  19. package/ai/agent/buildSystemPrompt.ts +1 -2
  20. package/ai/agent/cliExecutor.ts +330 -19
  21. package/ai/agent/createAgentSchema.ts +22 -0
  22. package/ai/agent/hooks/fetchPublicAgents.ts +14 -39
  23. package/ai/agent/hooks/usePublicAgents.ts +90 -192
  24. package/ai/agent/publicAgentCatalog.ts +359 -0
  25. package/ai/agent/publicAgentIdentity.ts +76 -0
  26. package/ai/agent/server/fetchPublicAgents.ts +21 -46
  27. package/ai/agent/serverOrigin.ts +7 -0
  28. package/ai/agent/streamAgentChatTurn.ts +23 -21
  29. package/ai/agent/streamAgentChatTurnUtils.ts +292 -6
  30. package/ai/agent/types.ts +2 -0
  31. package/ai/agent/web/agentDisplayUtils.ts +171 -0
  32. package/ai/agent/web/useAgentModelAvatarComponent.ts +32 -0
  33. package/ai/ai.locale.ts +8 -0
  34. package/ai/chat/sendOpenAICompletionsRequest.native.ts +15 -0
  35. package/ai/chat/sendOpenAICompletionsRequest.ts +93 -1
  36. package/ai/chat/sendOpenAIResponseRequest.ts +86 -9
  37. package/ai/chat/updateTotalUsage.ts +7 -0
  38. package/ai/llm/deepinfra.ts +30 -15
  39. package/ai/llm/mistral.ts +3 -4
  40. package/ai/llm/providers.ts +2 -0
  41. package/ai/llm/types.ts +15 -0
  42. package/ai/memory/capture.ts +3 -3
  43. package/ai/memory/consolidate.ts +2 -2
  44. package/ai/memory/delete.ts +4 -3
  45. package/ai/memory/query.ts +3 -3
  46. package/ai/memory/remember.ts +2 -2
  47. package/ai/memory/store.ts +3 -3
  48. package/ai/memory/storeShared.ts +3 -2
  49. package/ai/policy/commercialMultiplier.ts +16 -0
  50. package/ai/token/billingAdminAuditEvent.ts +68 -0
  51. package/ai/token/billingAdminAuditEventWriter.ts +41 -0
  52. package/ai/token/billingAnomaly.ts +90 -0
  53. package/ai/token/billingAnomalyLifecycle.ts +54 -0
  54. package/ai/token/billingAnomalyLifecycleWriter.ts +44 -0
  55. package/ai/token/billingAnomalyWriter.ts +41 -0
  56. package/ai/token/calculatePrice.ts +3 -2
  57. package/ai/token/deepinfraReconciliation.ts +153 -0
  58. package/ai/token/deepinfraRequestIdQuery.ts +92 -0
  59. package/ai/token/externalToolCost.ts +54 -41
  60. package/ai/token/missingUsageEstimate.ts +12 -3
  61. package/ai/token/normalizeUsage.ts +45 -5
  62. package/ai/token/openaiReconciliation.ts +188 -0
  63. package/ai/token/providerBillableEvent.ts +84 -0
  64. package/ai/token/providerBillableEventWriter.ts +36 -0
  65. package/ai/token/providerBillingAnomalyDrilldown.ts +308 -0
  66. package/ai/token/providerBillingDrilldown.ts +361 -0
  67. package/ai/token/providerBillingHealthReport.ts +366 -0
  68. package/ai/token/providerCall.ts +144 -0
  69. package/ai/token/providerCallSweeper.ts +168 -0
  70. package/ai/token/providerCallWriter.ts +33 -0
  71. package/ai/token/providerCredential.ts +89 -0
  72. package/ai/token/providerCredentialAnomaly.ts +154 -0
  73. package/ai/token/providerCredentialLifecycle.ts +59 -0
  74. package/ai/token/providerCredentialLifecycleWriter.ts +44 -0
  75. package/ai/token/providerCredentialRegistry.ts +83 -0
  76. package/ai/token/providerCredentialRegistryCommand.ts +97 -0
  77. package/ai/token/providerCredentialRegistryList.ts +124 -0
  78. package/ai/token/providerCredentialRegistryResolver.ts +150 -0
  79. package/ai/token/providerCredentialRegistryWriter.ts +41 -0
  80. package/ai/token/providerCredentialRotationCommand.ts +102 -0
  81. package/ai/token/providerCredentialRuntime.ts +56 -0
  82. package/ai/token/providerDispatchIntent.ts +67 -0
  83. package/ai/token/providerDispatchIntentWriter.ts +36 -0
  84. package/ai/token/providerGateway.ts +260 -0
  85. package/ai/token/providerReconciliation.ts +148 -0
  86. package/ai/token/providerReconciliationLocal.ts +97 -0
  87. package/ai/token/providerReconciliationRunner.ts +165 -0
  88. package/ai/token/providerReconciliationWriter.ts +41 -0
  89. package/ai/token/ratingResult.ts +202 -0
  90. package/ai/token/ratingResultWriter.ts +33 -0
  91. package/ai/token/serverDialogProjection.ts +5 -3
  92. package/ai/token/serverTokenWriter.ts +11 -3
  93. package/ai/token/types.ts +10 -0
  94. package/ai/tools/agent/callAgentTool.ts +3 -4
  95. package/ai/tools/agent/presets/appBuilderPreset.ts +5 -7
  96. package/ai/tools/agent/runStreamingAgentTool.ts +1 -2
  97. package/ai/tools/agent/streamParallelAgentsTool.ts +2 -3
  98. package/ai/tools/readXPostTool.ts +1 -5
  99. package/app/admin/adminPages.ts +9 -0
  100. package/app/i18n/i18n.config.ts +5 -0
  101. package/app/i18n/translations/pricing.locale.ts +397 -0
  102. package/app/utils/desktopAgentRuntimeStatusClient.ts +5 -4
  103. package/app/utils/desktopAgentRuntimeTurnClient.ts +4 -1
  104. package/app/utils/imageUtils.ts +64 -34
  105. package/auth/adminPermissions.ts +18 -0
  106. package/auth/authSlice.ts +26 -12
  107. package/auth/hooks/useFetchUsers.ts +3 -0
  108. package/auth/routes.ts +46 -0
  109. package/auth/server/accessActivity.ts +4 -3
  110. package/auth/server/adminPermissions.ts +43 -0
  111. package/auth/server/adminUsageReport.ts +375 -0
  112. package/auth/server/billingAnomalies.ts +235 -0
  113. package/auth/server/billingUsageReport.ts +41 -2
  114. package/auth/server/creatorEarningCreditConversion.ts +10 -2
  115. package/auth/server/deduct.ts +14 -7
  116. package/auth/server/delete.ts +10 -2
  117. package/auth/server/disable.ts +4 -3
  118. package/auth/server/emailAutomation.ts +7 -5
  119. package/auth/server/emailDbConfig.ts +4 -2
  120. package/auth/server/emailDelivery.ts +24 -20
  121. package/auth/server/emailDeliveryGuards.ts +10 -7
  122. package/auth/server/emailPreferences.ts +6 -4
  123. package/auth/server/emailReport.ts +6 -4
  124. package/auth/server/emailRuntimeConfig.ts +3 -3
  125. package/auth/server/emailScenarioNotifications.ts +9 -8
  126. package/auth/server/enable.ts +4 -3
  127. package/auth/server/getRechargeHistory.ts +3 -2
  128. package/auth/server/getUser.ts +3 -2
  129. package/auth/server/gptProAccess.ts +44 -0
  130. package/auth/server/inviteReward.ts +10 -7
  131. package/auth/server/listusers.ts +6 -4
  132. package/auth/server/login.ts +2 -2
  133. package/auth/server/productEntitlements.ts +7 -4
  134. package/auth/server/productPurchase.ts +10 -2
  135. package/auth/server/providerBillingDrilldown.ts +47 -0
  136. package/auth/server/providerBillingHealth.ts +71 -0
  137. package/auth/server/providerCredentials.ts +136 -0
  138. package/auth/server/recharge.ts +14 -8
  139. package/auth/server/revokeSessions.ts +4 -3
  140. package/auth/server/route.ts +77 -0
  141. package/auth/server/sendEmail.ts +5 -4
  142. package/auth/server/signup.ts +10 -3
  143. package/auth/server/token.ts +53 -55
  144. package/auth/server/tokenUsageBilling.ts +18 -7
  145. package/auth/server/usageManagementAccess.ts +43 -0
  146. package/auth/server/usageReport.ts +59 -0
  147. package/auth/types.ts +12 -0
  148. package/auth/utils.ts +24 -22
  149. package/authCommands.ts +36 -2
  150. package/buildPublish.ts +3 -1
  151. package/buildPublishArtifactAssembly.ts +62 -1
  152. package/buildPublishImportAnalysis.ts +21 -16
  153. package/chat/dialog/dialogLaunchScope.ts +32 -0
  154. package/chat/dialog/objectAssistantRegistry.ts +2 -2
  155. package/chat/dialog/useCreateDialog.ts +1 -1
  156. package/chat/hooks/useChatInput.ts +41 -10
  157. package/chat/messages/messageSlice.ts +5 -1
  158. package/chat/messages/pendingAttachmentParts.ts +28 -2
  159. package/chat/messages/sendFirstMessage.ts +76 -79
  160. package/chat/messages/types.ts +9 -0
  161. package/chat/messages/web/streamingMarkdownModel.ts +41 -0
  162. package/chat/messages/web/useStreamingReveal.ts +91 -0
  163. package/chat/web/messageInputAgentUi.ts +94 -6
  164. package/cliEnvHelpers.ts +8 -0
  165. package/cliRuntimeDoctorReport.ts +193 -0
  166. package/client/agentConfigResolver.test.ts +0 -2
  167. package/client/agentRun.test.ts +171 -10
  168. package/client/agentRun.ts +44 -637
  169. package/client/agentRunInput.ts +10 -0
  170. package/client/agentRunLocalExecutor.ts +179 -0
  171. package/client/agentRunServerTransport.ts +394 -0
  172. package/client/agentRunTaskRunRecorder.ts +176 -0
  173. package/client/localRuntimeAdapter.test.ts +236 -9
  174. package/client/localRuntimeAdapter.ts +221 -23
  175. package/client/localToolPolicy.test.ts +28 -4
  176. package/connector-experimental/daemonLauncher.ts +38 -4
  177. package/connectorRunArtifact.ts +34 -10
  178. package/connectorWebSocketTarget.ts +9 -5
  179. package/core/builtinAgents.ts +155 -11
  180. package/create/space/contentLabels.ts +1 -1
  181. package/create/space/contentTypeMeta.ts +3 -2
  182. package/create/space/sidebarVisibleTypes.ts +27 -0
  183. package/create/space/space.locale.ts +76 -4
  184. package/database/actions/agentReadResolution.ts +2 -8
  185. package/database/actions/read.ts +11 -9
  186. package/database/actions/readAndWait.ts +10 -5
  187. package/database/server/agentDelegation.ts +3 -2
  188. package/database/server/authorityStoreConformance.ts +209 -0
  189. package/database/server/authorityStoreTypes.ts +31 -0
  190. package/database/server/coreDataProxy.ts +1 -1
  191. package/database/server/dataHandlers.ts +13 -5
  192. package/database/server/db.ts +15 -34
  193. package/database/server/delete.ts +88 -71
  194. package/database/server/emailRepository.ts +11 -9
  195. package/database/server/fileService.ts +2 -1
  196. package/database/server/legacyServerDb.ts +58 -0
  197. package/database/server/levelAuthorityStore.ts +75 -0
  198. package/database/server/memoryAuthorityStore.ts +133 -0
  199. package/database/server/patch.ts +13 -12
  200. package/database/server/query.ts +3 -2
  201. package/database/server/read.ts +33 -30
  202. package/database/server/resourceAccess.ts +7 -5
  203. package/database/server/serverStoreFactory.ts +124 -0
  204. package/database/server/spaceMemberAuthority.ts +3 -2
  205. package/database/server/storeBatchCompat.ts +37 -0
  206. package/database/server/testAuthorityStore.ts +76 -0
  207. package/database/server/write.ts +29 -27
  208. package/integrations/anthropic/anthropicModels.ts +12 -12
  209. package/integrations/deepseek/models.ts +67 -67
  210. package/integrations/google/models.ts +111 -53
  211. package/integrations/openai/models.ts +22 -22
  212. package/integrations/xai/models.ts +1 -1
  213. package/localRuntimeDb.ts +39 -2
  214. package/machineCommandPrompts.ts +2 -0
  215. package/machineCommands.ts +193 -63
  216. package/machineWsRunDispatch.ts +80 -15
  217. package/machineWsSession.ts +39 -2
  218. package/noloReadBridgePrompt.ts +16 -0
  219. package/package.json +99 -6
  220. package/render/layout/mainLayoutViewMode.ts +25 -0
  221. package/render/page/server/createPage.ts +3 -1
  222. package/render/page/server/handleCreatePage.ts +2 -11
  223. package/runtimeDoctorCommands.ts +15 -66
  224. package/server/api/methods.ts +34 -12
  225. package/server/api/tableHandlers.ts +6 -3
  226. package/server/authenticateToken.ts +47 -2
  227. package/server/billingLedgerRoutes.ts +15 -0
  228. package/server/buildManifest.ts +54 -0
  229. package/server/coreReadiness.ts +34 -25
  230. package/server/coreRuntime.ts +15 -10
  231. package/server/handlers/activityStatsHandler.ts +5 -2
  232. package/server/handlers/agentEmailRegistrationE2EHandler.ts +25 -23
  233. package/server/handlers/agentRun/agentLookup.ts +1 -7
  234. package/server/handlers/agentRun/autonomousRuntime.ts +11 -10
  235. package/server/handlers/agentRun/builtinAgents.ts +12 -88
  236. package/server/handlers/agentRun/continueDialogContext.ts +15 -3
  237. package/server/handlers/agentRun/{inheritedDialogPrompt.ts → conversationReference.ts} +3 -3
  238. package/server/handlers/agentRun/dialogLookup.ts +4 -3
  239. package/server/handlers/agentRun/index.ts +864 -404
  240. package/server/handlers/agentRun/localRuntimeBootstrap.ts +17 -1
  241. package/server/handlers/agentRun/loop.ts +920 -508
  242. package/server/handlers/agentRun/machineConnector.ts +56 -8
  243. package/server/handlers/agentRun/machineRunAudit.ts +3 -2
  244. package/server/handlers/agentRun/modelUsageToolHandlers.ts +13 -10
  245. package/server/handlers/agentRun/requestContext.ts +12 -8
  246. package/server/handlers/agentRun/runtimeExecutionContext.ts +15 -3
  247. package/server/handlers/agentRun/runtimePreparation.ts +26 -24
  248. package/server/handlers/agentRun/runtimeRouting.ts +25 -40
  249. package/server/handlers/agentRun/runtimeSystemMessages.ts +65 -0
  250. package/server/handlers/agentRun/saveDialog.ts +97 -87
  251. package/server/handlers/agentRun/taskRunToolHandler.ts +9 -7
  252. package/server/handlers/agentRun/toolExecutor.ts +42 -78
  253. package/server/handlers/agentRun/types.ts +2 -1
  254. package/server/handlers/appDeployStatusStore.ts +17 -10
  255. package/server/handlers/appDomainHandler.ts +21 -15
  256. package/server/handlers/appLegacyInfraCleanup.ts +5 -2
  257. package/server/handlers/appSandboxHandler.ts +29 -8
  258. package/server/handlers/appSpaceAccess.ts +15 -8
  259. package/server/handlers/chatHandler.ts +22 -2
  260. package/server/handlers/chatUpstreamRetry.ts +225 -2
  261. package/server/handlers/connector/connectorConnectionRegistry.ts +55 -7
  262. package/server/handlers/connector/connectorWebSocket.ts +14 -10
  263. package/server/handlers/desktopAgentRuntimeAdapter.ts +4 -4
  264. package/server/handlers/desktopAgentRuntimeHostCapabilities.ts +25 -0
  265. package/server/handlers/desktopAgentRuntimeReadiness.ts +62 -0
  266. package/server/handlers/desktopAgentRuntimeStatusHandler.ts +38 -30
  267. package/server/handlers/desktopAgentRuntimeTurnHandler.ts +7 -3
  268. package/server/handlers/desktopAgentRuntimeTurnService.ts +39 -45
  269. package/server/handlers/desktopLlamaRuntimeHandler.ts +85 -51
  270. package/server/handlers/desktopUpdaterHandler.ts +132 -24
  271. package/server/handlers/favoriteHandlers.ts +8 -2
  272. package/server/handlers/getDialogBillingHandler.ts +4 -3
  273. package/server/handlers/getTransactionsHandler.ts +5 -2
  274. package/server/handlers/machines/machineBinding.ts +1 -0
  275. package/server/handlers/machines/machineHandlers.ts +0 -14
  276. package/server/handlers/machines/machineInstallAssets.ts +4 -2
  277. package/server/handlers/notificationEmitter.ts +5 -3
  278. package/server/handlers/notificationsHandler.ts +5 -2
  279. package/server/handlers/providerCallsRecentHandler.ts +234 -0
  280. package/server/handlers/providerReconciliationRunHandler.ts +180 -0
  281. package/server/handlers/providerRequestIdsHandler.ts +105 -0
  282. package/server/handlers/tableAccess.ts +6 -2
  283. package/server/handlers/tableToolHandlers.ts +28 -14
  284. package/server/handlers/userSecretsHandler.ts +17 -6
  285. package/server/handlers/versionHandler.ts +9 -4
  286. package/server/handlers/versionStore.ts +18 -10
  287. package/server/html/ssrPreload.ts +5 -3
  288. package/server/payments/crypto/cryptoUsdcBasePaymentProvider.ts +11 -8
  289. package/server/payments/crypto/cryptoUsdcBaseScanner.ts +12 -7
  290. package/server/payments/crypto/cryptoUsdtTronPaymentProvider.ts +11 -8
  291. package/server/payments/crypto/cryptoUsdtTronScanner.ts +9 -7
  292. package/server/payments/waffo/waffoPaymentProvider.ts +12 -9
  293. package/server/runtimeRole.ts +15 -0
  294. package/server/scheduler/scheduledTaskRuntime.ts +4 -2
  295. package/server/scheduler/schedulerService.ts +2 -2
  296. package/server/taskRunBridgeRoutes.ts +8 -5
  297. package/share/server/fetchCommunityShares.ts +1 -1
  298. package/share/server/helpers.ts +19 -17
  299. package/share/server/importShare.ts +9 -13
  300. package/share/server/listCommunityShares.ts +4 -4
  301. package/share/server/purchaseDoc.ts +8 -16
  302. package/share/server/readCommunityShareCover.ts +3 -2
  303. package/share/server/readSharedTable.ts +14 -13
  304. package/share/server/tableReplication.ts +42 -39
  305. package/spaceAttachCommands.ts +135 -0
  306. package/spaceInternalCommandEntries.ts +2 -0
  307. package/ai/agent/runtimeServerBase.ts +0 -37
  308. package/server/handlers/desktopAgentRuntimeHostFacts.ts +0 -40
@@ -1,38 +1,30 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import { runLocalAgentTurn } from "../agentRuntimeLocal";
4
- import { LOCAL_AGENT_CONFIG_MISSING_CODE } from "../agent-runtime/localLoop";
5
- import type { LocalAgentToolEvent } from "../agent-runtime/localLoop";
3
+ import { normalizeAgentRunDialogLineage } from "../ai/agent/agentRunDialogLineage";
6
4
  import type { AgentRuntimeHostAdapter, AgentRuntimeRequestedMode } from "../agentRuntimeLocal";
7
5
  import type { EnvLike } from "../cliEnvHelpers";
8
6
  import type { OutputLike } from "../cliIoTypes";
9
- import { createCliLocalRuntimeAdapter } from "./localRuntimeAdapter";
10
- import { createStreamingTextWriter } from "./streamingOutput";
11
- import { prependTaskRunPrompt, type TaskRunPromptContext } from "./taskRunPrompt";
7
+ import type { TaskRunPromptContext } from "./taskRunPrompt";
8
+ import { type TaskRunRecorder } from "./agentRunTaskRunRecorder";
9
+ import { buildUserInputContent } from "./agentRunInput";
12
10
  import {
13
- formatToolTraceEvent,
14
- nextLocalToolRoundLimit,
15
- parseLocalToolRoundLimitError,
16
- resolveLocalToolRoundRetryLimit,
17
- shouldCollectLocalToolEvidence,
18
- shouldTraceLocalTools,
19
- summarizeLocalToolEvidence,
20
- type TaskRunToolEvidence,
21
- } from "./agentRunLocalExecution";
22
- import {
23
- findServerPlatformTools,
24
11
  resolveRequestedRuntimeMode,
25
12
  shouldAttemptAutoLocal,
26
- shouldShowUsage,
27
13
  shouldSkipAutoLocalForServerPlatformTools,
28
14
  shouldUseScriptBridge,
29
15
  } from "./agentRunRuntimeSelection";
16
+ import {
17
+ isMissingLocalAgentConfigError,
18
+ refreshMissingLocalAgentConfig,
19
+ resolveLocalRuntimeAdapter,
20
+ runInjectedLocalAgentTurn,
21
+ runLocalAgentTurnWithAutoRoundExpansion,
22
+ } from "./agentRunLocalExecutor";
23
+ import { runHttpAgentTurn } from "./agentRunServerTransport";
30
24
  export { classifyTaskRunReviewStatus } from "./agentRunLocalExecution";
31
25
  export { findServerPlatformTools, shouldUseScriptBridge } from "./agentRunRuntimeSelection";
32
-
33
- type TaskRunAgentRole = "pm" | "frontend" | "fullstack" | "reviewer" | "codex";
34
26
 
35
- type RunAgentTurnOptions = {
27
+ export type RunAgentTurnOptions = {
36
28
  agentName: string;
37
29
  agentKey: string;
38
30
  serverUrl: string;
@@ -57,14 +49,7 @@ type RunAgentTurnOptions = {
57
49
  timeoutMs?: number;
58
50
  traceTools?: boolean;
59
51
  taskRunContext?: TaskRunPromptContext;
60
- taskRunRecorder?: (args: {
61
- options: RunAgentTurnOptions;
62
- status: "running" | "completed" | "failed";
63
- dialogId?: string;
64
- resultSummary?: string;
65
- errorCode?: string;
66
- toolEvidence?: TaskRunToolEvidence;
67
- }) => Promise<void>;
52
+ taskRunRecorder?: TaskRunRecorder<RunAgentTurnOptions>;
68
53
  scriptPathExists?: (path: string) => boolean;
69
54
  fetchImpl?: typeof fetch;
70
55
  };
@@ -74,241 +59,12 @@ export type RunAgentTurnResult = {
74
59
  dialogId?: string;
75
60
  streamInterrupted?: boolean;
76
61
  };
77
-
78
- function resolveServerPlatformToolNames(agentConfig: any) {
79
- return findServerPlatformTools([
80
- ...(Array.isArray(agentConfig?.toolNames) ? agentConfig.toolNames : []),
81
- ...(Array.isArray(agentConfig?.runtimeToolPolicy?.agentTools)
82
- ? agentConfig.runtimeToolPolicy.agentTools
83
- : []),
84
- ]);
85
- }
86
-
87
- function resolveAuthToken(env: EnvLike) {
88
- return env.AUTH_TOKEN || env.AUTH || env.BENCHMARK_AUTH_TOKEN || "";
89
- }
90
-
91
- function buildDefaultLocalRuntimeAdapter(options: RunAgentTurnOptions) {
92
- return createCliLocalRuntimeAdapter({
93
- env: options.env,
94
- fetchImpl: options.fetchImpl,
95
- cwd: options.localRuntimeCwd,
96
- output: options.output,
97
- });
98
- }
99
-
100
- function resolveLocalRuntimeAdapter(options: RunAgentTurnOptions) {
101
- return (
102
- options.localRuntimeAdapter ||
103
- options.localRuntimeAdapterFactory?.(options.env, { cwd: options.localRuntimeCwd }) ||
104
- buildDefaultLocalRuntimeAdapter(options)
105
- );
106
- }
107
-
108
- function buildUserInputContent(message: string, imageUrls: string[] = []) {
109
- if (imageUrls.length === 0) return message;
110
- return [
111
- ...(message.trim() ? [{ type: "text" as const, text: message }] : []),
112
- ...imageUrls.map((url) => ({
113
- type: "image_url" as const,
114
- image_url: { url },
115
- })),
116
- ];
117
- }
118
-
119
- function isMissingLocalAgentConfigError(error: unknown, agentRef: string) {
120
- return Boolean(
121
- error &&
122
- typeof error === "object" &&
123
- "code" in error &&
124
- (error as { code?: string; agentRef?: string }).code === LOCAL_AGENT_CONFIG_MISSING_CODE &&
125
- (error as { code?: string; agentRef?: string }).agentRef === agentRef
126
- );
127
- }
128
-
129
62
 
130
- function inferTaskRunAgentRole(agentRef: string): TaskRunAgentRole {
131
- const normalized = agentRef.toLowerCase();
132
- if (normalized.includes("project-manager") || normalized.includes("manager")) return "pm";
133
- if (normalized.includes("frontend")) return "frontend";
134
- if (normalized.includes("fullstack")) return "fullstack";
135
- if (normalized.includes("review")) return "reviewer";
136
- return "codex";
63
+ function resolveAuthToken(env: EnvLike) {
64
+ return env.AUTH_TOKEN || env.AUTH || env.BENCHMARK_AUTH_TOKEN || "";
137
65
  }
138
66
 
139
- async function runTaskRunCli(args: {
140
- options: RunAgentTurnOptions;
141
- cliArgs: string[];
142
- }) {
143
- const scriptPath = join(args.options.scriptDir, "taskRun.ts");
144
- const proc = Bun.spawn({
145
- cmd: [process.execPath, scriptPath, ...args.cliArgs],
146
- stdout: "pipe",
147
- stderr: "pipe",
148
- env: {
149
- ...process.env,
150
- ...args.options.env,
151
- BASE_URL: args.options.serverUrl,
152
- },
153
- });
154
- const [stdout, stderr, exitCode] = await Promise.all([
155
- new Response(proc.stdout).text(),
156
- new Response(proc.stderr).text(),
157
- proc.exited,
158
- ]);
159
- if (exitCode !== 0) {
160
- throw new Error((stderr || stdout || `taskRun.ts exited ${exitCode}`).trim());
161
- }
162
- }
163
-
164
- async function defaultTaskRunRecorder(args: {
165
- options: RunAgentTurnOptions;
166
- status: "running" | "completed" | "failed";
167
- dialogId?: string;
168
- resultSummary?: string;
169
- errorCode?: string;
170
- toolEvidence?: TaskRunToolEvidence;
171
- }) {
172
- const context = args.options.taskRunContext;
173
- if (!context?.rowDbKey) return;
174
- const role = inferTaskRunAgentRole(args.options.agentName || args.options.agentKey);
175
- if (role === "reviewer" && args.status !== "running") {
176
- await runTaskRunCli({
177
- options: args.options,
178
- cliArgs: [
179
- "request-review",
180
- "--row-dbkey",
181
- context.rowDbKey,
182
- "--base-url",
183
- args.options.serverUrl,
184
- "--reviewer-agent-key",
185
- args.options.agentKey,
186
- ...(context.artifactIds?.length ? ["--artifact-ids", context.artifactIds.join(",")] : []),
187
- ...(args.dialogId ? ["--dialog-id", args.dialogId] : []),
188
- ],
189
- });
190
- }
191
- await runTaskRunCli({
192
- options: args.options,
193
- cliArgs: [
194
- "record-agent-run",
195
- "--row-dbkey",
196
- context.rowDbKey,
197
- "--base-url",
198
- args.options.serverUrl,
199
- "--agent-key",
200
- args.options.agentKey,
201
- "--role",
202
- role,
203
- "--run-status",
204
- args.status,
205
- ...(context.workItemId ? ["--work-item-id", context.workItemId] : []),
206
- ...(args.dialogId ? ["--dialog-id", args.dialogId] : []),
207
- ...(args.resultSummary ? ["--result-summary", args.resultSummary.slice(0, 240)] : []),
208
- ...(args.errorCode ? ["--error-code", args.errorCode] : []),
209
- ...(args.toolEvidence?.toolsUsed?.length
210
- ? ["--tools-used", args.toolEvidence.toolsUsed.join(",")]
211
- : []),
212
- ...(args.toolEvidence?.summary
213
- ? ["--tool-trace-summary", JSON.stringify(args.toolEvidence.summary)]
214
- : []),
215
- ],
216
- });
217
- if (context.workItemId && args.dialogId) {
218
- await runTaskRunCli({
219
- options: args.options,
220
- cliArgs: [
221
- "update-work-item",
222
- "--row-dbkey",
223
- context.rowDbKey,
224
- "--base-url",
225
- args.options.serverUrl,
226
- "--id",
227
- context.workItemId,
228
- "--dialog-ids",
229
- args.dialogId,
230
- ],
231
- });
232
- }
233
- if (role === "reviewer" && args.status !== "running") {
234
- const reviewStatus =
235
- args.status === "failed" ? "blocked" : classifyTaskRunReviewStatus(args.resultSummary);
236
- if (reviewStatus) {
237
- await runTaskRunCli({
238
- options: args.options,
239
- cliArgs: [
240
- "review-result",
241
- "--row-dbkey",
242
- context.rowDbKey,
243
- "--base-url",
244
- args.options.serverUrl,
245
- "--review-status",
246
- reviewStatus,
247
- "--reviewer-agent-key",
248
- args.options.agentKey,
249
- ...(context.artifactIds?.length ? ["--artifact-ids", context.artifactIds.join(",")] : []),
250
- ...(args.dialogId ? ["--dialog-id", args.dialogId] : []),
251
- ],
252
- });
253
- }
254
- }
255
- }
256
-
257
- async function recordTaskRunOutcome(args: {
258
- options: RunAgentTurnOptions;
259
- status: "running" | "completed" | "failed";
260
- dialogId?: string;
261
- resultSummary?: string;
262
- errorCode?: string;
263
- toolEvidence?: TaskRunToolEvidence;
264
- }) {
265
- if (!args.options.taskRunContext?.rowDbKey) return;
266
- try {
267
- await (args.options.taskRunRecorder ?? defaultTaskRunRecorder)(args);
268
- } catch (error) {
269
- args.options.output.write(
270
- `[nolo] task-run writeback failed: ${error instanceof Error ? error.message : String(error)}\n`
271
- );
272
- }
273
- }
274
-
275
- function formatUsage(usage: any, dialogId: unknown) {
276
- const parts: string[] = [];
277
- if (typeof dialogId === "string" && dialogId) parts.push(`dialog=${dialogId}`);
278
-
279
- const input = usage?.input_tokens ?? usage?.prompt_tokens ?? 0;
280
- const output = usage?.output_tokens ?? usage?.completion_tokens ?? 0;
281
- if (input || output) parts.push(`tokens=${input}+${output}`);
282
-
283
- return parts.length ? ` (${parts.join(" ")})` : "";
284
- }
285
-
286
- function buildTransportErrorHint(serverUrl: string, error: unknown) {
287
- const endpoint = `${serverUrl}/api/agent/run`;
288
- const reason = error instanceof Error ? error.message : String(error);
289
-
290
- let detail =
291
- `[nolo] Could not reach ${endpoint}.\n` +
292
- `Reason: ${reason}\n`;
293
-
294
- try {
295
- const parsed = new URL(serverUrl);
296
- if (parsed.hostname === "127.0.0.1" || parsed.hostname === "localhost") {
297
- detail +=
298
- "If you meant local dev, start the local API first.\n" +
299
- "Otherwise set NOLO_SERVER to a reachable server, or re-run `nolo login --server https://nolo.chat`.\n";
300
- return detail;
301
- }
302
- } catch {
303
- // Keep the generic hint below when serverUrl is not a valid absolute URL.
304
- }
305
-
306
- detail +=
307
- "Check NOLO_SERVER / BASE_URL and make sure the configured server is reachable.\n";
308
- return detail;
309
- }
310
-
311
- async function runScriptBridge(options: RunAgentTurnOptions, scriptPath: string) {
67
+ async function runScriptBridge(options: RunAgentTurnOptions, scriptPath: string) {
312
68
  options.output.write(`\n${options.agentName} -> working via local script...\n\n`);
313
69
  const proc = Bun.spawn({
314
70
  cmd: [
@@ -361,394 +117,45 @@ async function runScriptBridge(options: RunAgentTurnOptions, scriptPath: string)
361
117
  }
362
118
  return { exitCode };
363
119
  }
364
-
365
- async function runHttpAgentTurn(options: RunAgentTurnOptions, authToken: string) {
366
- options.output.write(`\n${options.agentName} -> working...\n`);
367
-
368
- const fetchImpl = options.fetchImpl ?? fetch;
369
- let res: Response;
370
- try {
371
- res = await fetchImpl(`${options.serverUrl}/api/agent/run`, {
372
- method: "POST",
373
- headers: {
374
- Authorization: `Bearer ${authToken}`,
375
- "Content-Type": "application/json",
376
- },
377
- body: JSON.stringify({
378
- agentKey: options.agentKey,
379
- userInput: buildUserInputContent(
380
- prependTaskRunPrompt(options.message, options.taskRunContext),
381
- options.imageUrls
382
- ),
383
- runtimeContext: {
384
- surface: "cli",
385
- host: "terminal",
386
- runtime: "bun",
387
- entrypoint: "nolo-cli",
388
- capabilities: ["text-io", "streaming", "slash-commands"],
389
- ...(options.taskRunContext
390
- ? {
391
- taskRun: {
392
- rowDbKey: options.taskRunContext.rowDbKey,
393
- ...(options.taskRunContext.taskRunId
394
- ? { taskRunId: options.taskRunContext.taskRunId }
395
- : {}),
396
- ...(options.taskRunContext.workItemId
397
- ? { workItemId: options.taskRunContext.workItemId }
398
- : {}),
399
- ...(options.taskRunContext.artifactIds?.length
400
- ? { artifactIds: options.taskRunContext.artifactIds }
401
- : {}),
402
- },
403
- }
404
- : {}),
405
- },
406
- ...(options.continueDialogId
407
- ? { continueDialogId: options.continueDialogId }
408
- : {}),
409
- ...(options.spaceId ? { spaceId: options.spaceId } : {}),
410
- ...(options.category ? { category: options.category } : {}),
411
- ...(options.inheritedFromDialogKey
412
- ? { inheritedFromDialogKey: options.inheritedFromDialogKey }
413
- : {}),
414
- ...(options.parentDialogId ? { parentDialogId: options.parentDialogId } : {}),
415
- ...(options.background ? { background: true } : {}),
416
- ...(typeof options.maxToolRounds === "number" ? { maxRounds: options.maxToolRounds } : {}),
417
- ...(typeof options.timeoutMs === "number" ? { timeoutMs: options.timeoutMs } : {}),
418
- stream: !options.noStream && !options.background,
419
- }),
420
- });
421
- } catch (error) {
422
- options.output.write(buildTransportErrorHint(options.serverUrl, error));
423
- return { exitCode: 1 };
424
- }
425
-
426
- const contentType = res.headers.get("content-type") || "";
427
- if (contentType.includes("text/event-stream") && res.body) {
428
- const result = await readStreamingAgentRun(options, res);
429
- await recordTaskRunOutcome({
430
- options,
431
- status: result.streamInterrupted
432
- ? "running"
433
- : result.exitCode === 0
434
- ? "completed"
435
- : "failed",
436
- dialogId: result.dialogId,
437
- ...(result.exitCode !== 0 ? { errorCode: "STREAM_FAILED" } : {}),
438
- });
439
- return result;
440
- }
441
-
442
- let data: any = {};
443
- try {
444
- data = await res.json();
445
- } catch {
446
- data = {};
447
- }
448
-
449
- if (!res.ok) {
450
- options.output.write(`[nolo] Agent request failed: HTTP ${res.status}\n`);
451
- if (data?.error || data?.message) {
452
- options.output.write(`${data.error || data.message}\n`);
453
- }
454
- await recordTaskRunOutcome({
455
- options,
456
- status: "failed",
457
- errorCode: `HTTP_${res.status}`,
458
- resultSummary: String(data?.error || data?.message || "").trim() || undefined,
459
- });
460
- return { exitCode: 1 };
461
- }
462
-
463
- const content = String(data?.content ?? data?.message ?? "").trim();
464
- if (content) {
465
- options.output.write(`\n${options.agentName} > ${content}\n`);
466
- } else {
467
- options.output.write(`\n${options.agentName} > (no text response)\n`);
468
- }
469
-
470
- const usage = formatUsage(data?.usage, data?.dialogId);
471
- if (usage && shouldShowUsage(options.env)) options.output.write(`${usage}\n`);
472
- const result = {
473
- exitCode: 0,
474
- ...(typeof data?.dialogId === "string" && data.dialogId
475
- ? { dialogId: data.dialogId }
476
- : {}),
477
- };
478
- await recordTaskRunOutcome({
479
- options,
480
- status: options.background ? "running" : "completed",
481
- dialogId: result.dialogId,
482
- ...(!options.background && content ? { resultSummary: content } : {}),
483
- });
484
- return result;
485
- }
486
-
487
- async function runInjectedLocalAgentTurn(options: RunAgentTurnOptions) {
488
- return runLocalAgentTurnWithAutoRoundExpansion(options, { reportFailure: true });
489
- }
490
-
491
- async function refreshMissingLocalAgentConfig(options: RunAgentTurnOptions) {
492
- const adapter = resolveLocalRuntimeAdapter(options);
493
- if (!adapter) return false;
494
- const agentConfig = await adapter.loadAgentConfig(options.agentKey);
495
- return Boolean(agentConfig);
496
- }
497
-
498
- async function runLocalAgentTurnWithAutoRoundExpansion(
499
- options: RunAgentTurnOptions,
500
- settings: { reportFailure: boolean }
501
- ) {
502
- const maxRetryLimit = resolveLocalToolRoundRetryLimit(options);
503
- let currentMaxToolRounds = options.maxToolRounds;
504
- let lastResult: Awaited<ReturnType<typeof runLocalAgentTurnForCli>> | null = null;
505
-
506
- while (true) {
507
- const attemptOptions = {
508
- ...options,
509
- ...(typeof currentMaxToolRounds === "number" ? { maxToolRounds: currentMaxToolRounds } : {}),
510
- };
511
- const result = await runLocalAgentTurnForCli(attemptOptions, { reportFailure: false });
512
- lastResult = result;
513
- if (result.exitCode === 0) return result;
514
-
515
- const exhaustedRounds = parseLocalToolRoundLimitError(result.localError);
516
- if (exhaustedRounds === null) break;
517
-
518
- const nextMaxToolRounds = nextLocalToolRoundLimit(exhaustedRounds);
519
- if (nextMaxToolRounds > maxRetryLimit) break;
520
-
521
- options.output.write(
522
- `[nolo] Local agent used all ${exhaustedRounds} tool rounds; retrying with ${nextMaxToolRounds}.\n`
523
- );
524
- currentMaxToolRounds = nextMaxToolRounds;
525
- }
526
-
527
- if (settings.reportFailure && lastResult?.localError) {
528
- options.output.write(
529
- `[nolo] Local agent run failed: ${
530
- lastResult.localError instanceof Error ? lastResult.localError.message : String(lastResult.localError)
531
- }\n`
532
- );
533
- await recordTaskRunOutcome({
534
- options,
535
- status: "failed",
536
- errorCode: "LOCAL_AGENT_FAILED",
537
- resultSummary:
538
- lastResult.localError instanceof Error ? lastResult.localError.message : String(lastResult.localError),
539
- toolEvidence: lastResult.toolEvidence,
540
- });
541
- }
542
- return lastResult ?? { exitCode: 1 };
543
- }
544
-
545
- async function runLocalAgentTurnForCli(
546
- options: RunAgentTurnOptions,
547
- settings: { reportFailure: boolean }
548
- ) {
549
- const adapter = resolveLocalRuntimeAdapter(options);
550
- if (!adapter) {
551
- options.output.write("[nolo] Local runtime was requested but no local runtime adapter is available.\n");
552
- return { exitCode: 1 };
553
- }
554
120
 
555
- options.output.write(`\n${options.agentName} -> working locally...\n`);
556
- const toolEvents: LocalAgentToolEvent[] = [];
557
- try {
558
- const traceLocalTools = shouldTraceLocalTools(options);
559
- const collectToolEvidence = shouldCollectLocalToolEvidence(options);
560
- const result = await runLocalAgentTurn({
561
- adapter,
562
- agentRef: options.agentKey,
563
- input: buildUserInputContent(
564
- prependTaskRunPrompt(options.message, options.taskRunContext),
565
- options.imageUrls
566
- ),
567
- continueDialogId: options.continueDialogId,
568
- spaceId: options.spaceId,
569
- category: options.category,
570
- inheritedFromDialogKey: options.inheritedFromDialogKey,
571
- parentDialogId: options.parentDialogId,
572
- background: options.background,
573
- noStream: options.noStream,
574
- maxToolRounds: options.maxToolRounds,
575
- ...(traceLocalTools || collectToolEvidence
576
- ? {
577
- onToolEvent: (event) => {
578
- if (collectToolEvidence) toolEvents.push(event);
579
- if (traceLocalTools) options.output.write(formatToolTraceEvent(event));
580
- },
581
- }
582
- : {}),
583
- });
584
- const content = result.content.trim();
585
- if (content) {
586
- options.output.write(`\n${options.agentName} > ${content}\n`);
587
- } else {
588
- options.output.write(`\n${options.agentName} > (no text response)\n`);
589
- }
590
- await recordTaskRunOutcome({
591
- options,
592
- status: options.background ? "running" : "completed",
593
- dialogId: result.dialogId,
594
- ...(!options.background && content ? { resultSummary: content } : {}),
595
- toolEvidence: summarizeLocalToolEvidence(toolEvents),
596
- });
597
- return { exitCode: 0, dialogId: result.dialogId };
598
- } catch (error) {
599
- if (settings.reportFailure) {
600
- options.output.write(
601
- `[nolo] Local agent run failed: ${
602
- error instanceof Error ? error.message : String(error)
603
- }\n`
604
- );
605
- }
606
- return { exitCode: 1, localError: error, toolEvidence: summarizeLocalToolEvidence(toolEvents) };
607
- }
608
- }
609
-
610
- async function readStreamingAgentRun(
611
- options: RunAgentTurnOptions,
612
- res: Response,
613
- ): Promise<RunAgentTurnResult> {
614
- const reader = res.body?.getReader();
615
- if (!reader) {
616
- options.output.write("[nolo] Agent stream response did not include a readable body.\n");
617
- return { exitCode: 1 };
618
- }
619
-
620
- const decoder = new TextDecoder();
621
- const writer = createStreamingTextWriter({
622
- write: (chunk) => options.output.write(chunk),
623
- });
624
- let buffer = "";
625
- let content = "";
626
- let dialogId: string | undefined;
627
- let usage: any;
628
- let hasPrintedLabel = false;
629
-
630
- const printLabel = () => {
631
- if (hasPrintedLabel) return;
632
- options.output.write(`\n${options.agentName} > `);
633
- hasPrintedLabel = true;
634
- };
635
-
636
- const handlePayload = (payload: any) => {
637
- if (typeof payload?.dialogId === "string" && payload.dialogId.trim()) {
638
- dialogId = payload.dialogId;
639
- }
640
- if (payload?.error || payload?.type === "error") {
641
- throw new Error(String(payload.error || payload.message || "Agent stream failed"));
642
- }
643
- if (payload?.type === "done") {
644
- usage = payload.usage;
645
- return;
646
- }
647
- if (payload?.type === "dialog" || payload?.type === "status") {
648
- return;
649
- }
650
-
651
- const chunk =
652
- payload?.type === "text"
653
- ? payload.content
654
- : typeof payload?.chunk === "string"
655
- ? payload.chunk
656
- : "";
657
- if (!chunk) return;
658
-
659
- printLabel();
660
- content += chunk;
661
- writer.push(chunk);
662
- };
663
-
664
- try {
665
- while (true) {
666
- const { done, value } = await reader.read();
667
- if (done) break;
668
-
669
- buffer += decoder.decode(value, { stream: true });
670
- const events = buffer.split("\n\n");
671
- buffer = events.pop() ?? "";
672
-
673
- for (const event of events) {
674
- const dataLines = event
675
- .split("\n")
676
- .filter((line) => line.startsWith("data:"))
677
- .map((line) => line.slice(5).trim())
678
- .filter(Boolean);
679
- for (const raw of dataLines) {
680
- handlePayload(JSON.parse(raw));
681
- }
682
- }
683
- }
684
- if (buffer.trim()) {
685
- const raw = buffer
686
- .split("\n")
687
- .find((line) => line.startsWith("data:"))
688
- ?.slice(5)
689
- .trim();
690
- if (raw) handlePayload(JSON.parse(raw));
691
- }
692
- } catch (error) {
693
- const message = error instanceof Error ? error.message : String(error);
694
- if (dialogId) {
695
- options.output.write(
696
- `\n[nolo] Agent stream transport interrupted after dialog ${dialogId} was created: ${message}\n`
697
- );
698
- options.output.write("[nolo] The agent run may still finish on the server; read the dialog before retrying.\n");
699
- return { exitCode: 0, dialogId, streamInterrupted: true };
700
- }
701
- options.output.write(`\n[nolo] Agent stream failed: ${message}\n`);
702
- return { exitCode: 1 };
703
- } finally {
704
- writer.flushAll();
705
- }
706
-
707
- if (!content) {
708
- options.output.write(`\n${options.agentName} > (no text response)\n`);
709
- } else {
710
- options.output.write("\n");
711
- }
712
-
713
- const usageText = formatUsage(usage, dialogId);
714
- if (usageText && shouldShowUsage(options.env)) options.output.write(`${usageText}\n`);
715
- return {
716
- exitCode: 0,
717
- ...(dialogId ? { dialogId } : {}),
718
- };
719
- }
720
-
721
121
  export async function runAgentTurn(options: RunAgentTurnOptions) {
122
+ const dialogLineage = normalizeAgentRunDialogLineage(options);
123
+ const effectiveOptions: RunAgentTurnOptions = {
124
+ ...options,
125
+ continueDialogId: dialogLineage.continueDialogId,
126
+ inheritedFromDialogKey: dialogLineage.inheritedFromDialogKey,
127
+ parentDialogId: dialogLineage.parentDialogId,
128
+ };
722
129
  const authToken = resolveAuthToken(options.env);
723
- const scriptPath = join(options.scriptDir, "chatWithAgent.ts");
130
+ const scriptPath = join(effectiveOptions.scriptDir, "chatWithAgent.ts");
724
131
  const scriptPathExists = (options.scriptPathExists ?? existsSync)(scriptPath);
725
- const runtimeMode = resolveRequestedRuntimeMode(options);
132
+ const runtimeMode = resolveRequestedRuntimeMode(effectiveOptions);
726
133
 
727
134
  if (runtimeMode === "local") {
728
- return runInjectedLocalAgentTurn(options);
135
+ return runInjectedLocalAgentTurn(effectiveOptions);
729
136
  }
730
137
 
731
- if (runtimeMode === "auto" && shouldAttemptAutoLocal(options)) {
138
+ if (runtimeMode === "auto" && shouldAttemptAutoLocal(effectiveOptions)) {
732
139
  const skipLocal = await shouldSkipAutoLocalForServerPlatformTools({
733
- ...options,
734
- resolveLocalRuntimeAdapter: () => resolveLocalRuntimeAdapter(options),
140
+ ...effectiveOptions,
141
+ resolveLocalRuntimeAdapter: () => resolveLocalRuntimeAdapter(effectiveOptions),
735
142
  });
736
143
  if (!skipLocal) {
737
- const localResult = await runLocalAgentTurnWithAutoRoundExpansion(options, { reportFailure: false });
144
+ const localResult = await runLocalAgentTurnWithAutoRoundExpansion(effectiveOptions, { reportFailure: false });
738
145
  if (localResult.exitCode === 0) {
739
146
  return {
740
147
  exitCode: localResult.exitCode,
741
148
  ...(localResult.dialogId ? { dialogId: localResult.dialogId } : {}),
742
149
  };
743
150
  }
744
- if (isMissingLocalAgentConfigError(localResult.localError, options.agentKey)) {
745
- options.output.write(
151
+ if (isMissingLocalAgentConfigError(localResult.localError, effectiveOptions.agentKey)) {
152
+ effectiveOptions.output.write(
746
153
  `[nolo] Local agent config was missing; refreshing from the configured server and retrying local once.\n`
747
154
  );
748
155
  try {
749
- const refreshed = await refreshMissingLocalAgentConfig(options);
156
+ const refreshed = await refreshMissingLocalAgentConfig(effectiveOptions);
750
157
  if (refreshed) {
751
- const retriedLocalResult = await runLocalAgentTurnWithAutoRoundExpansion(options, {
158
+ const retriedLocalResult = await runLocalAgentTurnWithAutoRoundExpansion(effectiveOptions, {
752
159
  reportFailure: false,
753
160
  });
754
161
  if (retriedLocalResult.exitCode === 0) {
@@ -766,16 +173,16 @@ export async function runAgentTurn(options: RunAgentTurnOptions) {
766
173
  }
767
174
 
768
175
  if (shouldUseScriptBridge({ hasAuthToken: Boolean(authToken), scriptPathExists })) {
769
- return runScriptBridge(options, scriptPath);
176
+ return runScriptBridge(effectiveOptions, scriptPath);
770
177
  }
771
-
772
- if (!authToken) {
773
- options.output.write(
774
- "[nolo] This install needs an auth token before it can talk to agents.\n" +
775
- "Set AUTH_TOKEN, or use the repo-local CLI where the dev script bridge is available.\n"
776
- );
178
+
179
+ if (!authToken) {
180
+ effectiveOptions.output.write(
181
+ "[nolo] This install needs an auth token before it can talk to agents.\n" +
182
+ "Set AUTH_TOKEN, or use the repo-local CLI where the dev script bridge is available.\n"
183
+ );
777
184
  return { exitCode: 1 };
778
185
  }
779
186
 
780
- return runHttpAgentTurn(options, authToken);
781
- }
187
+ return runHttpAgentTurn(effectiveOptions, { authToken });
188
+ }