@clinebot/core 0.0.36 → 0.0.37

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 (228) hide show
  1. package/dist/ClineCore.d.ts +312 -3
  2. package/dist/ClineCore.d.ts.map +1 -1
  3. package/dist/account/cline-account-service.d.ts.map +1 -1
  4. package/dist/cron/cron-event-ingress.d.ts +38 -0
  5. package/dist/cron/cron-event-ingress.d.ts.map +1 -0
  6. package/dist/cron/cron-materializer.d.ts +36 -0
  7. package/dist/cron/cron-materializer.d.ts.map +1 -0
  8. package/dist/cron/cron-reconciler.d.ts +62 -0
  9. package/dist/cron/cron-reconciler.d.ts.map +1 -0
  10. package/dist/cron/cron-report-writer.d.ts +41 -0
  11. package/dist/cron/cron-report-writer.d.ts.map +1 -0
  12. package/dist/cron/cron-runner.d.ts +43 -0
  13. package/dist/cron/cron-runner.d.ts.map +1 -0
  14. package/dist/cron/cron-schema.d.ts +3 -0
  15. package/dist/cron/cron-schema.d.ts.map +1 -0
  16. package/dist/cron/cron-service.d.ts +57 -0
  17. package/dist/cron/cron-service.d.ts.map +1 -0
  18. package/dist/cron/cron-spec-parser.d.ts +27 -0
  19. package/dist/cron/cron-spec-parser.d.ts.map +1 -0
  20. package/dist/cron/cron-watcher.d.ts +23 -0
  21. package/dist/cron/cron-watcher.d.ts.map +1 -0
  22. package/dist/cron/scheduler.d.ts +3 -1
  23. package/dist/cron/scheduler.d.ts.map +1 -1
  24. package/dist/cron/sqlite-cron-store.d.ts +230 -0
  25. package/dist/cron/sqlite-cron-store.d.ts.map +1 -0
  26. package/dist/extensions/plugin/plugin-config-loader.d.ts +7 -1
  27. package/dist/extensions/plugin/plugin-config-loader.d.ts.map +1 -1
  28. package/dist/extensions/plugin/plugin-loader.d.ts +10 -6
  29. package/dist/extensions/plugin/plugin-loader.d.ts.map +1 -1
  30. package/dist/extensions/plugin/plugin-sandbox.d.ts +7 -1
  31. package/dist/extensions/plugin/plugin-sandbox.d.ts.map +1 -1
  32. package/dist/extensions/plugin-sandbox-bootstrap.js +236 -275
  33. package/dist/extensions/tools/constants.d.ts +1 -0
  34. package/dist/extensions/tools/constants.d.ts.map +1 -1
  35. package/dist/extensions/tools/definitions.d.ts +2 -3
  36. package/dist/extensions/tools/definitions.d.ts.map +1 -1
  37. package/dist/extensions/tools/executors/editor.d.ts.map +1 -1
  38. package/dist/extensions/tools/helpers.d.ts +1 -0
  39. package/dist/extensions/tools/helpers.d.ts.map +1 -1
  40. package/dist/extensions/tools/index.d.ts +1 -2
  41. package/dist/extensions/tools/index.d.ts.map +1 -1
  42. package/dist/extensions/tools/presets.d.ts +1 -1
  43. package/dist/extensions/tools/schemas.d.ts +25 -3
  44. package/dist/extensions/tools/schemas.d.ts.map +1 -1
  45. package/dist/extensions/tools/team/delegated-agent.d.ts +2 -2
  46. package/dist/extensions/tools/team/delegated-agent.d.ts.map +1 -1
  47. package/dist/extensions/tools/team/multi-agent.d.ts +7 -3
  48. package/dist/extensions/tools/team/multi-agent.d.ts.map +1 -1
  49. package/dist/extensions/tools/team/team-tools.d.ts.map +1 -1
  50. package/dist/extensions/tools/types.d.ts +0 -5
  51. package/dist/extensions/tools/types.d.ts.map +1 -1
  52. package/dist/hooks/hook-bridge.d.ts +118 -0
  53. package/dist/hooks/hook-bridge.d.ts.map +1 -0
  54. package/dist/hooks/hook-file-hooks.d.ts +2 -1
  55. package/dist/hooks/hook-file-hooks.d.ts.map +1 -1
  56. package/dist/hooks/hook-registry.d.ts +16 -0
  57. package/dist/hooks/hook-registry.d.ts.map +1 -0
  58. package/dist/hub/browser-websocket.d.ts.map +1 -1
  59. package/dist/hub/client.d.ts +7 -1
  60. package/dist/hub/client.d.ts.map +1 -1
  61. package/dist/hub/daemon-entry.js +721 -461
  62. package/dist/hub/daemon.d.ts.map +1 -1
  63. package/dist/hub/defaults.d.ts +8 -4
  64. package/dist/hub/defaults.d.ts.map +1 -1
  65. package/dist/hub/index.js +665 -415
  66. package/dist/hub/runtime-handlers.d.ts.map +1 -1
  67. package/dist/hub/server.d.ts +18 -0
  68. package/dist/hub/server.d.ts.map +1 -1
  69. package/dist/hub/session-client.d.ts +3 -0
  70. package/dist/hub/session-client.d.ts.map +1 -1
  71. package/dist/hub/start-shared-server.d.ts.map +1 -1
  72. package/dist/hub/ui-client.d.ts +1 -0
  73. package/dist/hub/ui-client.d.ts.map +1 -1
  74. package/dist/index.d.ts +9 -7
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +756 -467
  77. package/dist/llms/cline-recommended-models.d.ts +20 -0
  78. package/dist/llms/cline-recommended-models.d.ts.map +1 -0
  79. package/dist/llms/handler-factory.d.ts +16 -0
  80. package/dist/llms/handler-factory.d.ts.map +1 -0
  81. package/dist/llms/provider-defaults.d.ts.map +1 -1
  82. package/dist/llms/provider-settings.d.ts +45 -2
  83. package/dist/llms/provider-settings.d.ts.map +1 -1
  84. package/dist/llms/runtime-registry.d.ts.map +1 -1
  85. package/dist/runtime/agent-config-adapter.d.ts +148 -0
  86. package/dist/runtime/agent-config-adapter.d.ts.map +1 -0
  87. package/dist/runtime/agent-runtime-config-builder.d.ts +96 -0
  88. package/dist/runtime/agent-runtime-config-builder.d.ts.map +1 -0
  89. package/dist/runtime/history.d.ts +6 -0
  90. package/dist/runtime/history.d.ts.map +1 -1
  91. package/dist/runtime/host.d.ts.map +1 -1
  92. package/dist/runtime/loop-detection.d.ts +59 -0
  93. package/dist/runtime/loop-detection.d.ts.map +1 -0
  94. package/dist/runtime/mistake-tracker.d.ts +69 -0
  95. package/dist/runtime/mistake-tracker.d.ts.map +1 -0
  96. package/dist/runtime/runtime-builder.d.ts.map +1 -1
  97. package/dist/runtime/runtime-event-adapter.d.ts +102 -0
  98. package/dist/runtime/runtime-event-adapter.d.ts.map +1 -0
  99. package/dist/runtime/runtime-host.d.ts +28 -3
  100. package/dist/runtime/runtime-host.d.ts.map +1 -1
  101. package/dist/runtime/session-runtime-orchestrator.d.ts +261 -0
  102. package/dist/runtime/session-runtime-orchestrator.d.ts.map +1 -0
  103. package/dist/runtime/session-runtime.d.ts +16 -3
  104. package/dist/runtime/session-runtime.d.ts.map +1 -1
  105. package/dist/runtime/user-input-builder.d.ts +24 -0
  106. package/dist/runtime/user-input-builder.d.ts.map +1 -0
  107. package/dist/services/index.js +28 -0
  108. package/dist/services/local-runtime-bootstrap.d.ts.map +1 -1
  109. package/dist/services/plugin-tools.d.ts.map +1 -1
  110. package/dist/services/providers/local-provider-registry.d.ts +197 -21
  111. package/dist/services/providers/local-provider-registry.d.ts.map +1 -1
  112. package/dist/services/providers/local-provider-service.d.ts +3 -1
  113. package/dist/services/providers/local-provider-service.d.ts.map +1 -1
  114. package/dist/services/session-data.d.ts.map +1 -1
  115. package/dist/services/session-telemetry.d.ts +7 -2
  116. package/dist/services/session-telemetry.d.ts.map +1 -1
  117. package/dist/services/storage/file-team-store.d.ts.map +1 -1
  118. package/dist/services/storage/provider-settings-legacy-migration.d.ts.map +1 -1
  119. package/dist/services/storage/provider-settings-manager.d.ts +1 -0
  120. package/dist/services/storage/provider-settings-manager.d.ts.map +1 -1
  121. package/dist/services/storage/sqlite-team-store.d.ts.map +1 -1
  122. package/dist/session/conversation-store.d.ts +30 -0
  123. package/dist/session/conversation-store.d.ts.map +1 -0
  124. package/dist/session/message-builder.d.ts +65 -0
  125. package/dist/session/message-builder.d.ts.map +1 -0
  126. package/dist/session/session-manifest.d.ts +1 -1
  127. package/dist/transports/hub.d.ts +14 -3
  128. package/dist/transports/hub.d.ts.map +1 -1
  129. package/dist/transports/local.d.ts +14 -4
  130. package/dist/transports/local.d.ts.map +1 -1
  131. package/dist/transports/remote.d.ts.map +1 -1
  132. package/dist/types/chat-schema.d.ts +5 -5
  133. package/dist/types/config.d.ts +9 -0
  134. package/dist/types/config.d.ts.map +1 -1
  135. package/dist/types/events.d.ts +7 -6
  136. package/dist/types/events.d.ts.map +1 -1
  137. package/dist/types/provider-settings.d.ts +2 -2
  138. package/dist/types/provider-settings.d.ts.map +1 -1
  139. package/dist/types/session.d.ts +5 -2
  140. package/dist/types/session.d.ts.map +1 -1
  141. package/dist/types.d.ts +4 -4
  142. package/dist/types.d.ts.map +1 -1
  143. package/package.json +4 -4
  144. package/src/ClineCore.ts +691 -6
  145. package/src/account/cline-account-service.ts +44 -6
  146. package/src/cron/cron-event-ingress.ts +357 -0
  147. package/src/cron/cron-materializer.ts +97 -0
  148. package/src/cron/cron-reconciler.ts +241 -0
  149. package/src/cron/cron-report-writer.ts +153 -0
  150. package/src/cron/cron-runner.ts +495 -0
  151. package/src/cron/cron-schema.ts +127 -0
  152. package/src/cron/cron-service.ts +163 -0
  153. package/src/cron/cron-spec-parser.ts +489 -0
  154. package/src/cron/cron-watcher.ts +102 -0
  155. package/src/cron/index.ts +10 -0
  156. package/src/cron/scheduler.ts +141 -6
  157. package/src/cron/sqlite-cron-store.ts +1286 -0
  158. package/src/extensions/plugin/plugin-config-loader.ts +21 -1
  159. package/src/extensions/plugin/plugin-loader.ts +25 -9
  160. package/src/extensions/plugin/plugin-sandbox-bootstrap.ts +151 -1
  161. package/src/extensions/plugin/plugin-sandbox.ts +131 -7
  162. package/src/extensions/tools/constants.ts +2 -0
  163. package/src/extensions/tools/definitions.ts +31 -22
  164. package/src/extensions/tools/executors/editor.ts +4 -3
  165. package/src/extensions/tools/helpers.ts +24 -0
  166. package/src/extensions/tools/index.ts +1 -2
  167. package/src/extensions/tools/presets.ts +1 -1
  168. package/src/extensions/tools/schemas.ts +13 -18
  169. package/src/extensions/tools/team/delegated-agent.ts +8 -3
  170. package/src/extensions/tools/team/multi-agent.ts +135 -19
  171. package/src/extensions/tools/team/team-tools.ts +151 -91
  172. package/src/extensions/tools/types.ts +0 -6
  173. package/src/hooks/hook-bridge.ts +489 -0
  174. package/src/hooks/hook-file-hooks.ts +58 -3
  175. package/src/hooks/hook-registry.ts +257 -0
  176. package/src/hub/browser-websocket.ts +26 -4
  177. package/src/hub/client.ts +72 -13
  178. package/src/hub/daemon-entry.ts +35 -0
  179. package/src/hub/daemon.ts +117 -14
  180. package/src/hub/defaults.ts +39 -12
  181. package/src/hub/runtime-handlers.ts +4 -3
  182. package/src/hub/server.ts +506 -77
  183. package/src/hub/session-client.ts +43 -1
  184. package/src/hub/start-shared-server.ts +3 -0
  185. package/src/hub/ui-client.ts +4 -0
  186. package/src/index.ts +46 -1
  187. package/src/llms/cline-recommended-models.ts +167 -0
  188. package/src/llms/handler-factory.ts +56 -0
  189. package/src/llms/provider-defaults.ts +17 -1
  190. package/src/llms/provider-settings.ts +48 -1
  191. package/src/llms/runtime-registry.ts +1 -0
  192. package/src/runtime/agent-config-adapter.ts +636 -0
  193. package/src/runtime/agent-runtime-config-builder.ts +205 -0
  194. package/src/runtime/error-feedback.ts +142 -0
  195. package/src/runtime/history.ts +137 -0
  196. package/src/runtime/host.ts +22 -0
  197. package/src/runtime/loop-detection.ts +162 -0
  198. package/src/runtime/mistake-tracker.ts +221 -0
  199. package/src/runtime/runtime-builder.ts +61 -5
  200. package/src/runtime/runtime-event-adapter.ts +412 -0
  201. package/src/runtime/runtime-host.ts +45 -1
  202. package/src/runtime/session-runtime-orchestrator.ts +1253 -0
  203. package/src/runtime/session-runtime.ts +16 -2
  204. package/src/runtime/user-input-builder.ts +167 -0
  205. package/src/services/local-runtime-bootstrap.ts +128 -22
  206. package/src/services/plugin-tools.ts +1 -0
  207. package/src/services/providers/local-provider-registry.ts +273 -57
  208. package/src/services/providers/local-provider-service.ts +67 -7
  209. package/src/services/session-data.ts +16 -14
  210. package/src/services/session-telemetry.ts +6 -15
  211. package/src/services/storage/file-team-store.ts +1 -5
  212. package/src/services/storage/provider-settings-legacy-migration.ts +8 -47
  213. package/src/services/storage/provider-settings-manager.ts +16 -1
  214. package/src/services/storage/sqlite-team-store.ts +1 -5
  215. package/src/session/conversation-store.ts +77 -0
  216. package/src/session/message-builder.ts +941 -0
  217. package/src/transports/hub.ts +458 -33
  218. package/src/transports/local.ts +296 -65
  219. package/src/transports/remote.ts +1 -0
  220. package/src/types/config.ts +9 -0
  221. package/src/types/events.ts +8 -6
  222. package/src/types/index.ts +3 -0
  223. package/src/types/provider-settings.ts +8 -1
  224. package/src/types/session.ts +5 -2
  225. package/src/types.ts +15 -1
  226. package/dist/cron/index.d.ts +0 -6
  227. package/dist/cron/index.d.ts.map +0 -1
  228. package/dist/services/telemetry/index.js +0 -28
@@ -1,12 +1,14 @@
1
1
  import { readFile, stat } from "node:fs/promises";
2
2
  import { homedir } from "node:os";
3
3
  import { isAbsolute, join, resolve } from "node:path";
4
- import { Agent } from "@clinebot/agents";
5
4
  import type * as LlmsProviders from "@clinebot/llms";
6
5
  import {
7
6
  type AgentConfig,
8
7
  type AgentEvent,
9
8
  type AgentResult,
9
+ type AutomationEventEnvelope,
10
+ type BasicLogger,
11
+ type BasicLogMetadata,
10
12
  createSessionId,
11
13
  type ITelemetryService,
12
14
  isLikelyAuthError,
@@ -28,6 +30,11 @@ import { createSpawnAgentTool, type TeamEvent } from "../extensions/tools/team";
28
30
  import type { HookEventPayload } from "../hooks";
29
31
  import { DefaultRuntimeBuilder } from "../runtime/runtime-builder";
30
32
  import type {
33
+ PendingPromptMutationResult,
34
+ PendingPromptsAction,
35
+ PendingPromptsDeleteInput,
36
+ PendingPromptsListInput,
37
+ PendingPromptsUpdateInput,
31
38
  RuntimeHost,
32
39
  RuntimeHostSubscribeOptions,
33
40
  SendSessionInput,
@@ -41,6 +48,7 @@ import {
41
48
  RuntimeOAuthTokenManager,
42
49
  } from "../runtime/runtime-oauth-token-manager";
43
50
  import type { RuntimeBuilder } from "../runtime/session-runtime";
51
+ import { SessionRuntime } from "../runtime/session-runtime-orchestrator";
44
52
  import {
45
53
  type AgentEventContext,
46
54
  buildTelemetryAgentIdentity,
@@ -97,8 +105,12 @@ import {
97
105
  } from "../session/session-team-coordination";
98
106
  import { SessionSource, type SessionStatus } from "../types/common";
99
107
  import type { CoreSessionConfig } from "../types/config";
100
- import type { CoreSessionEvent } from "../types/events";
101
- import type { ActiveSession, PreparedTurnInput } from "../types/session";
108
+ import type { CoreSessionEvent, SessionPendingPrompt } from "../types/events";
109
+ import type {
110
+ ActiveSession,
111
+ PendingPrompt,
112
+ PreparedTurnInput,
113
+ } from "../types/session";
102
114
  import type { SessionRecord } from "../types/sessions";
103
115
  import {
104
116
  cloneAccumulatedUsage,
@@ -133,9 +145,9 @@ function toActiveSessionRecord(session: ActiveSession): SessionRecord {
133
145
  source: session.source,
134
146
  pid: process.pid,
135
147
  startedAt: session.startedAt,
136
- endedAt: null,
137
- exitCode: null,
138
- status: "running",
148
+ endedAt: session.endedAt ?? null,
149
+ exitCode: session.exitCode ?? null,
150
+ status: session.status,
139
151
  interactive: session.interactive,
140
152
  provider: session.config.providerId,
141
153
  model: session.config.modelId,
@@ -176,7 +188,7 @@ export interface LocalRuntimeHostOptions {
176
188
  distinctId?: string;
177
189
  sessionService: SessionBackend;
178
190
  runtimeBuilder?: RuntimeBuilder;
179
- createAgent?: (config: AgentConfig) => Agent;
191
+ createAgent?: (config: AgentConfig) => SessionRuntime;
180
192
  defaultToolExecutors?: Partial<ToolExecutors>;
181
193
  toolPolicies?: AgentConfig["toolPolicies"];
182
194
  providerSettingsManager?: ProviderSettingsManager;
@@ -197,7 +209,7 @@ export class LocalRuntimeHost implements RuntimeHost {
197
209
  public readonly runtimeAddress = undefined;
198
210
  private readonly sessionService: SessionBackend;
199
211
  private readonly runtimeBuilder: RuntimeBuilder;
200
- private readonly createAgentInstance: (config: AgentConfig) => Agent;
212
+ private readonly createAgentInstance: (config: AgentConfig) => SessionRuntime;
201
213
  private readonly defaultToolExecutors?: Partial<ToolExecutors>;
202
214
  private readonly defaultToolPolicies?: AgentConfig["toolPolicies"];
203
215
  private readonly providerSettingsManager: ProviderSettingsManager;
@@ -222,7 +234,7 @@ export class LocalRuntimeHost implements RuntimeHost {
222
234
  this.sessionService = options.sessionService;
223
235
  this.runtimeBuilder = options.runtimeBuilder ?? new DefaultRuntimeBuilder();
224
236
  this.createAgentInstance =
225
- options.createAgent ?? ((config) => new Agent(config));
237
+ options.createAgent ?? ((config) => new SessionRuntime(config));
226
238
  this.defaultToolExecutors = options.defaultToolExecutors;
227
239
  this.defaultToolPolicies = options.toolPolicies;
228
240
  this.providerSettingsManager =
@@ -286,6 +298,13 @@ export class LocalRuntimeHost implements RuntimeHost {
286
298
 
287
299
  const sessionToolExecutors =
288
300
  input.localRuntime?.defaultToolExecutors ?? this.defaultToolExecutors;
301
+ const inputLocalConfig = input.localRuntime?.configOverrides as
302
+ | Partial<CoreSessionConfig>
303
+ | undefined;
304
+ const pluginEventFallbackLogger =
305
+ inputLocalConfig?.extensionContext?.logger ?? inputLocalConfig?.logger;
306
+ const pluginEventFallbackAutomation =
307
+ inputLocalConfig?.extensionContext?.automation;
289
308
  let bootstrap!: Awaited<ReturnType<typeof prepareLocalRuntimeBootstrap>>;
290
309
  bootstrap = await prepareLocalRuntimeBootstrap({
291
310
  input: startInput,
@@ -297,7 +316,21 @@ export class LocalRuntimeHost implements RuntimeHost {
297
316
  defaultToolPolicies: this.defaultToolPolicies,
298
317
  defaultRequestToolApproval: this.defaultRequestToolApproval,
299
318
  defaultFetch: this.defaultFetch,
300
- onPluginEvent: (event) => void this.handlePluginEvent(sessionId, event),
319
+ onPluginEvent: (event) => {
320
+ if (event.name === "plugin_log") {
321
+ this.handlePluginLog(
322
+ sessionId,
323
+ event.payload,
324
+ pluginEventFallbackLogger,
325
+ );
326
+ return;
327
+ }
328
+ void this.handlePluginEvent(
329
+ sessionId,
330
+ event,
331
+ pluginEventFallbackAutomation,
332
+ );
333
+ },
301
334
  onTeamEvent: (event: TeamEvent) => {
302
335
  void this.handleTeamEvent(sessionId, event);
303
336
  bootstrap.config.onTeamEvent?.(event);
@@ -324,6 +357,7 @@ export class LocalRuntimeHost implements RuntimeHost {
324
357
  const tools = [...runtime.tools, ...(configWithProvider.extraTools ?? [])];
325
358
 
326
359
  const agentConfig = {
360
+ sessionId,
327
361
  providerId: providerConfig.providerId,
328
362
  modelId: providerConfig.modelId,
329
363
  apiKey: providerConfig.apiKey,
@@ -356,10 +390,13 @@ export class LocalRuntimeHost implements RuntimeHost {
356
390
  this.onAgentEvent(sessionId, configWithProvider, event),
357
391
  } as AgentConfig;
358
392
  const agent = this.createAgentInstance(agentConfig);
393
+ if (agentConfig.onEvent) {
394
+ agent.subscribeEvents(agentConfig.onEvent);
395
+ }
359
396
  runtime.registerLeadAgent?.(agent);
360
397
  const rootAgentIdentity = buildTelemetryAgentIdentity({
361
- agentId: this.readAgentId(agent),
362
- conversationId: this.readAgentConversationId(agent),
398
+ agentId: agent.getAgentId(),
399
+ conversationId: agent.getConversationId(),
363
400
  teamId: runtime.teamRuntime?.getTeamId(),
364
401
  teamName: runtime.teamRuntime?.getTeamName(),
365
402
  teamRole: runtime.teamRuntime ? "lead" : undefined,
@@ -367,7 +404,6 @@ export class LocalRuntimeHost implements RuntimeHost {
367
404
  emitSessionCreationTelemetry(
368
405
  configWithProvider,
369
406
  sessionId,
370
- source,
371
407
  requestedSessionId.length > 0,
372
408
  workspacePath,
373
409
  rootAgentIdentity,
@@ -385,7 +421,7 @@ export class LocalRuntimeHost implements RuntimeHost {
385
421
  ulid: sessionId,
386
422
  teamId: runtime.teamRuntime.getTeamId(),
387
423
  teamName: runtime.teamRuntime.getTeamName(),
388
- leadAgentId: this.readAgentId(agent),
424
+ leadAgentId: agent.getAgentId(),
389
425
  restoredFromPersistence: runtime.teamRestoredFromPersistence === true,
390
426
  });
391
427
  }
@@ -400,6 +436,7 @@ export class LocalRuntimeHost implements RuntimeHost {
400
436
  runtime,
401
437
  agent,
402
438
  started: false,
439
+ status: "running",
403
440
  aborting: false,
404
441
  interactive: input.interactive === true,
405
442
  persistedMessages: startInput.initialMessages,
@@ -412,6 +449,18 @@ export class LocalRuntimeHost implements RuntimeHost {
412
449
  };
413
450
  this.sessions.set(sessionId, active);
414
451
  this.emitStatus(sessionId, "running");
452
+ if ((startInput.initialMessages?.length ?? 0) > 0) {
453
+ await this.ensureSessionPersisted(active);
454
+ await this.invoke<void>(
455
+ "persistSessionMessages",
456
+ active.sessionId,
457
+ startInput.initialMessages,
458
+ active.config.systemPrompt,
459
+ );
460
+ if (!startInput.prompt?.trim()) {
461
+ await this.updateStatus(active, "completed", 0);
462
+ }
463
+ }
415
464
 
416
465
  let result: AgentResult | undefined;
417
466
  try {
@@ -441,15 +490,7 @@ export class LocalRuntimeHost implements RuntimeHost {
441
490
 
442
491
  async send(input: SendSessionInput): Promise<AgentResult | undefined> {
443
492
  const session = this.getSessionOrThrow(input.sessionId);
444
- const canStartRun =
445
- typeof (session.agent as Agent & { canStartRun?: () => boolean })
446
- .canStartRun === "function"
447
- ? (
448
- session.agent as Agent & {
449
- canStartRun: () => boolean;
450
- }
451
- ).canStartRun()
452
- : true;
493
+ const canStartRun = session.agent.canStartRun();
453
494
  const delivery =
454
495
  input.delivery ??
455
496
  (session.interactive && !canStartRun ? ("queue" as const) : undefined);
@@ -491,6 +532,122 @@ export class LocalRuntimeHost implements RuntimeHost {
491
532
  }
492
533
  }
493
534
 
535
+ async pendingPrompts(
536
+ action: "list",
537
+ input: PendingPromptsListInput,
538
+ ): Promise<SessionPendingPrompt[]>;
539
+ async pendingPrompts(
540
+ action: "update",
541
+ input: PendingPromptsUpdateInput,
542
+ ): Promise<PendingPromptMutationResult>;
543
+ async pendingPrompts(
544
+ action: "delete",
545
+ input: PendingPromptsDeleteInput,
546
+ ): Promise<PendingPromptMutationResult>;
547
+ async pendingPrompts(
548
+ action: PendingPromptsAction,
549
+ input:
550
+ | PendingPromptsListInput
551
+ | PendingPromptsUpdateInput
552
+ | PendingPromptsDeleteInput,
553
+ ): Promise<SessionPendingPrompt[] | PendingPromptMutationResult> {
554
+ switch (action) {
555
+ case "list":
556
+ return this.listPendingPromptEntries(input.sessionId);
557
+ case "update":
558
+ return this.editPendingPromptEntry(input as PendingPromptsUpdateInput);
559
+ case "delete":
560
+ return this.deletePendingPromptEntry(
561
+ input as PendingPromptsDeleteInput,
562
+ );
563
+ }
564
+ }
565
+
566
+ private listPendingPromptEntries(sessionId: string): SessionPendingPrompt[] {
567
+ const session = this.sessions.get(sessionId);
568
+ return session ? this.snapshotPendingPrompts(session) : [];
569
+ }
570
+
571
+ private editPendingPromptEntry(
572
+ input: PendingPromptsUpdateInput,
573
+ ): PendingPromptMutationResult {
574
+ const session = this.sessions.get(input.sessionId);
575
+ if (!session || session.aborting) {
576
+ return { sessionId: input.sessionId, prompts: [], updated: false };
577
+ }
578
+ const promptId = input.promptId.trim();
579
+ const index = session.pendingPrompts.findIndex(
580
+ (entry) => entry.id === promptId,
581
+ );
582
+ if (index < 0) {
583
+ return {
584
+ sessionId: input.sessionId,
585
+ prompts: this.snapshotPendingPrompts(session),
586
+ updated: false,
587
+ };
588
+ }
589
+
590
+ const existing = session.pendingPrompts[index]!;
591
+ const prompt =
592
+ input.prompt === undefined
593
+ ? existing.prompt
594
+ : normalizeUserInput(input.prompt).trim();
595
+ if (!prompt) {
596
+ throw new Error("prompt cannot be empty");
597
+ }
598
+ const delivery = input.delivery ?? existing.delivery;
599
+ const next: PendingPrompt = {
600
+ ...existing,
601
+ prompt,
602
+ delivery,
603
+ };
604
+ session.pendingPrompts.splice(index, 1);
605
+ if (delivery === "steer") {
606
+ session.pendingPrompts.unshift(next);
607
+ } else if (existing.delivery === "steer") {
608
+ session.pendingPrompts.push(next);
609
+ } else {
610
+ session.pendingPrompts.splice(index, 0, next);
611
+ }
612
+ this.emitPendingPrompts(session);
613
+ this.schedulePendingPromptDrain(input.sessionId, session);
614
+ return {
615
+ sessionId: input.sessionId,
616
+ prompts: this.snapshotPendingPrompts(session),
617
+ prompt: this.snapshotPendingPrompt(next),
618
+ updated: true,
619
+ };
620
+ }
621
+
622
+ private deletePendingPromptEntry(
623
+ input: PendingPromptsDeleteInput,
624
+ ): PendingPromptMutationResult {
625
+ const session = this.sessions.get(input.sessionId);
626
+ if (!session || session.aborting) {
627
+ return { sessionId: input.sessionId, prompts: [], removed: false };
628
+ }
629
+ const promptId = input.promptId.trim();
630
+ const index = session.pendingPrompts.findIndex(
631
+ (entry) => entry.id === promptId,
632
+ );
633
+ if (index < 0) {
634
+ return {
635
+ sessionId: input.sessionId,
636
+ prompts: this.snapshotPendingPrompts(session),
637
+ removed: false,
638
+ };
639
+ }
640
+ const [removed] = session.pendingPrompts.splice(index, 1);
641
+ this.emitPendingPrompts(session);
642
+ this.schedulePendingPromptDrain(input.sessionId, session);
643
+ return {
644
+ sessionId: input.sessionId,
645
+ prompts: this.snapshotPendingPrompts(session),
646
+ prompt: removed ? this.snapshotPendingPrompt(removed) : undefined,
647
+ removed: true,
648
+ };
649
+ }
650
+
494
651
  async getAccumulatedUsage(
495
652
  sessionId: string,
496
653
  ): Promise<SessionAccumulatedUsage | undefined> {
@@ -509,11 +666,7 @@ export class LocalRuntimeHost implements RuntimeHost {
509
666
  session.pendingPrompts.length = 0;
510
667
  this.emitPendingPrompts(session);
511
668
  }
512
- (
513
- session.agent as Agent & {
514
- abort: (abortReason?: unknown) => void;
515
- }
516
- ).abort(reason);
669
+ session.agent.abort(reason);
517
670
  }
518
671
 
519
672
  async stop(sessionId: string): Promise<void> {
@@ -525,11 +678,7 @@ export class LocalRuntimeHost implements RuntimeHost {
525
678
  });
526
679
  // Abort the agent first if it's running, so shutdown can proceed
527
680
  session.aborting = true;
528
- (
529
- session.agent as Agent & {
530
- abort: (abortReason?: unknown) => void;
531
- }
532
- ).abort(new Error("session_stop"));
681
+ session.agent.abort(new Error("session_stop"));
533
682
  await this.shutdownSession(session, {
534
683
  status: "cancelled",
535
684
  exitCode: 0,
@@ -870,10 +1019,11 @@ export class LocalRuntimeHost implements RuntimeHost {
870
1019
  ): Promise<void> {
871
1020
  if (hasPendingTeamRunWork(session)) return;
872
1021
  const isAborted = finishReason === "aborted" || session.aborting;
1022
+ const isError = finishReason === "error";
873
1023
  await this.shutdownSession(session, {
874
- status: isAborted ? "cancelled" : "completed",
875
- exitCode: 0,
876
- shutdownReason: "session_complete",
1024
+ status: isAborted ? "cancelled" : isError ? "failed" : "completed",
1025
+ exitCode: isError ? 1 : 0,
1026
+ shutdownReason: isError ? "session_error" : "session_complete",
877
1027
  endReason: finishReason,
878
1028
  });
879
1029
  }
@@ -977,6 +1127,9 @@ export class LocalRuntimeHost implements RuntimeHost {
977
1127
  latestManifest.ended_at = result.endedAt ?? nowIso();
978
1128
  latestManifest.exit_code = typeof exitCode === "number" ? exitCode : null;
979
1129
  session.artifacts.manifest = latestManifest;
1130
+ session.status = status;
1131
+ session.endedAt = latestManifest.ended_at;
1132
+ session.exitCode = latestManifest.exit_code;
980
1133
  await this.invoke<void>(
981
1134
  "writeSessionManifest",
982
1135
  session.artifacts.manifestPath,
@@ -988,7 +1141,31 @@ export class LocalRuntimeHost implements RuntimeHost {
988
1141
  private async handlePluginEvent(
989
1142
  rootSessionId: string,
990
1143
  event: { name: string; payload?: unknown },
1144
+ fallbackAutomation?: NonNullable<
1145
+ CoreSessionConfig["extensionContext"]
1146
+ >["automation"],
991
1147
  ): Promise<void> {
1148
+ if (event.name === "plugin_log") {
1149
+ this.handlePluginLog(rootSessionId, event.payload);
1150
+ return;
1151
+ }
1152
+ if (event.name === "automation_event") {
1153
+ const session = this.sessions.get(rootSessionId);
1154
+ const automation =
1155
+ session?.config.extensionContext?.automation ?? fallbackAutomation;
1156
+ if (!automation) {
1157
+ return;
1158
+ }
1159
+ const payload =
1160
+ event.payload && typeof event.payload === "object"
1161
+ ? (event.payload as AutomationEventEnvelope)
1162
+ : undefined;
1163
+ if (!payload) {
1164
+ return;
1165
+ }
1166
+ await automation.ingestEvent(payload);
1167
+ return;
1168
+ }
992
1169
  if (
993
1170
  event.name !== "steer_message" &&
994
1171
  event.name !== "queue_message" &&
@@ -1024,6 +1201,49 @@ export class LocalRuntimeHost implements RuntimeHost {
1024
1201
  });
1025
1202
  }
1026
1203
 
1204
+ private handlePluginLog(
1205
+ rootSessionId: string,
1206
+ payload: unknown,
1207
+ fallbackLogger?: BasicLogger,
1208
+ ): void {
1209
+ const session = this.sessions.get(rootSessionId);
1210
+ const logger =
1211
+ fallbackLogger ??
1212
+ session?.config.extensionContext?.logger ??
1213
+ session?.config.logger;
1214
+ if (!logger || !payload || typeof payload !== "object") {
1215
+ return;
1216
+ }
1217
+ const record = payload as Record<string, unknown>;
1218
+ const message = typeof record.message === "string" ? record.message : "";
1219
+ if (!message) {
1220
+ return;
1221
+ }
1222
+ const metadata =
1223
+ record.metadata && typeof record.metadata === "object"
1224
+ ? ({
1225
+ ...(record.metadata as Record<string, unknown>),
1226
+ } as BasicLogMetadata)
1227
+ : {};
1228
+ metadata.sessionId ??= rootSessionId;
1229
+ if (typeof record.pluginName === "string" && record.pluginName) {
1230
+ metadata.pluginName = record.pluginName;
1231
+ }
1232
+ if (record.level === "debug") {
1233
+ logger.debug(message, metadata);
1234
+ return;
1235
+ }
1236
+ if (record.level === "error") {
1237
+ if (logger.error) {
1238
+ logger.error(message, metadata);
1239
+ } else {
1240
+ logger.log(message, { ...metadata, severity: "error" });
1241
+ }
1242
+ return;
1243
+ }
1244
+ logger.log(message, metadata);
1245
+ }
1246
+
1027
1247
  /**
1028
1248
  * Consume the first steer-delivery pending prompt for injection into the
1029
1249
  * running agent loop. Called synchronously by the agent between iterations.
@@ -1097,6 +1317,21 @@ export class LocalRuntimeHost implements RuntimeHost {
1097
1317
  });
1098
1318
  }
1099
1319
  this.emitPendingPrompts(session);
1320
+ this.schedulePendingPromptDrain(sessionId, session);
1321
+ }
1322
+
1323
+ private schedulePendingPromptDrain(
1324
+ sessionId: string,
1325
+ session: ActiveSession,
1326
+ ): void {
1327
+ if (
1328
+ session.pendingPrompts.length === 0 ||
1329
+ session.aborting ||
1330
+ session.drainingPendingPrompts ||
1331
+ !session.agent.canStartRun()
1332
+ ) {
1333
+ return;
1334
+ }
1100
1335
  queueMicrotask(() => {
1101
1336
  void this.drainPendingPrompts(sessionId);
1102
1337
  });
@@ -1107,15 +1342,7 @@ export class LocalRuntimeHost implements RuntimeHost {
1107
1342
  if (!session || session.aborting || session.drainingPendingPrompts) {
1108
1343
  return;
1109
1344
  }
1110
- const canStartRun =
1111
- typeof (session.agent as Agent & { canStartRun?: () => boolean })
1112
- .canStartRun === "function"
1113
- ? (
1114
- session.agent as Agent & {
1115
- canStartRun: () => boolean;
1116
- }
1117
- ).canStartRun()
1118
- : true;
1345
+ const canStartRun = session.agent.canStartRun();
1119
1346
  if (!canStartRun) {
1120
1347
  return;
1121
1348
  }
@@ -1197,17 +1424,29 @@ export class LocalRuntimeHost implements RuntimeHost {
1197
1424
  type: "pending_prompts",
1198
1425
  payload: {
1199
1426
  sessionId: session.sessionId,
1200
- prompts: session.pendingPrompts.map((entry) => ({
1201
- id: entry.id,
1202
- prompt: entry.prompt,
1203
- delivery: entry.delivery,
1204
- attachmentCount:
1205
- (entry.userImages?.length ?? 0) + (entry.userFiles?.length ?? 0),
1206
- })),
1427
+ prompts: this.snapshotPendingPrompts(session),
1207
1428
  },
1208
1429
  });
1209
1430
  }
1210
1431
 
1432
+ private snapshotPendingPrompt(entry: PendingPrompt): SessionPendingPrompt {
1433
+ return {
1434
+ id: entry.id,
1435
+ prompt: entry.prompt,
1436
+ delivery: entry.delivery,
1437
+ attachmentCount:
1438
+ (entry.userImages?.length ?? 0) + (entry.userFiles?.length ?? 0),
1439
+ };
1440
+ }
1441
+
1442
+ private snapshotPendingPrompts(
1443
+ session: ActiveSession,
1444
+ ): SessionPendingPrompt[] {
1445
+ return session.pendingPrompts.map((entry) =>
1446
+ this.snapshotPendingPrompt(entry),
1447
+ );
1448
+ }
1449
+
1211
1450
  private emitPendingPromptSubmitted(
1212
1451
  session: ActiveSession,
1213
1452
  entry: {
@@ -1490,13 +1729,7 @@ export class LocalRuntimeHost implements RuntimeHost {
1490
1729
  session: ActiveSession,
1491
1730
  overrides: { apiKey?: string; modelId?: string },
1492
1731
  ): void {
1493
- const agentWithConnection = session.agent as Agent & {
1494
- updateConnection?: (overrides: {
1495
- apiKey?: string;
1496
- modelId?: string;
1497
- }) => void;
1498
- };
1499
- agentWithConnection.updateConnection?.(overrides);
1732
+ session.agent.updateConnection(overrides);
1500
1733
  }
1501
1734
 
1502
1735
  private getSessionAgentTelemetryIdentity(session: ActiveSession) {
@@ -1509,14 +1742,12 @@ export class LocalRuntimeHost implements RuntimeHost {
1509
1742
  });
1510
1743
  }
1511
1744
 
1512
- private readAgentId(agent: Agent): string | undefined {
1513
- return (agent as Agent & { getAgentId?: () => string }).getAgentId?.();
1745
+ private readAgentId(agent: SessionRuntime): string {
1746
+ return agent.getAgentId();
1514
1747
  }
1515
1748
 
1516
- private readAgentConversationId(agent: Agent): string | undefined {
1517
- return (
1518
- agent as Agent & { getConversationId?: () => string }
1519
- ).getConversationId?.();
1749
+ private readAgentConversationId(agent: SessionRuntime): string {
1750
+ return agent.getConversationId();
1520
1751
  }
1521
1752
 
1522
1753
  private emitStatus(sessionId: string, status: string): void {
@@ -16,6 +16,7 @@ export class RemoteRuntimeHost extends HubRuntimeHost {
16
16
  authToken: options.authToken,
17
17
  clientType: options.clientType ?? "core-remote-runtime",
18
18
  displayName: options.displayName ?? "core remote runtime",
19
+ requestToolApproval: options.requestToolApproval,
19
20
  },
20
21
  {
21
22
  workspaceRoot: options.workspaceRoot,
@@ -178,6 +178,15 @@ export interface CoreSessionConfig
178
178
  | "missionLogIntervalMs"
179
179
  | "maxConsecutiveMistakes"
180
180
  > {
181
+ /**
182
+ * Core/hub runtime session identifier.
183
+ *
184
+ * When provided, this becomes the host-owned id for persistence, hub
185
+ * subscriptions, send/abort/stop commands, and approval routing. When
186
+ * omitted, the runtime host creates one. This is distinct from the agent
187
+ * conversation id, which is generated by the conversation store for
188
+ * transcript/tool/hook context.
189
+ */
181
190
  sessionId?: string;
182
191
  workspaceRoot?: string;
183
192
  systemPrompt: string;
@@ -36,14 +36,16 @@ export interface SessionTeamProgressEvent {
36
36
  summary: import("@clinebot/shared").TeamProgressSummary;
37
37
  }
38
38
 
39
+ export interface SessionPendingPrompt {
40
+ id: string;
41
+ prompt: string;
42
+ delivery: "queue" | "steer";
43
+ attachmentCount: number;
44
+ }
45
+
39
46
  export interface SessionPendingPromptsEvent {
40
47
  sessionId: string;
41
- prompts: Array<{
42
- id: string;
43
- prompt: string;
44
- delivery: "queue" | "steer";
45
- attachmentCount: number;
46
- }>;
48
+ prompts: SessionPendingPrompt[];
47
49
  }
48
50
 
49
51
  export interface SessionPendingPromptSubmittedEvent {
@@ -9,6 +9,9 @@ export type {
9
9
  CoreSessionEvent,
10
10
  SessionChunkEvent,
11
11
  SessionEndedEvent,
12
+ SessionPendingPrompt,
13
+ SessionPendingPromptSubmittedEvent,
14
+ SessionPendingPromptsEvent,
12
15
  SessionTeamProgressEvent,
13
16
  SessionToolEvent,
14
17
  } from "./events";
@@ -1,12 +1,19 @@
1
1
  import { z } from "zod";
2
2
  import {
3
+ type ProviderClient,
3
4
  type ProviderConfig,
5
+ type ProviderProtocol,
4
6
  type ProviderSettings,
5
7
  ProviderSettingsSchema,
6
8
  toProviderConfig,
7
9
  } from "../llms/provider-settings";
8
10
 
9
- export type { ProviderConfig, ProviderSettings };
11
+ export type {
12
+ ProviderClient,
13
+ ProviderConfig,
14
+ ProviderProtocol,
15
+ ProviderSettings,
16
+ };
10
17
  export const ProviderSettingsSchemaTyped: z.ZodType<ProviderSettings> =
11
18
  ProviderSettingsSchema;
12
19
  export { toProviderConfig };
@@ -1,7 +1,7 @@
1
- import type { Agent } from "@clinebot/agents";
2
1
  import type * as LlmsProviders from "@clinebot/llms";
3
2
  import type { SessionAccumulatedUsage } from "../runtime/runtime-host";
4
3
  import type { BuiltRuntime } from "../runtime/session-runtime";
4
+ import type { SessionRuntime } from "../runtime/session-runtime-orchestrator";
5
5
  import type { SessionRow } from "../session/session-row";
6
6
  import type { RootSessionArtifacts } from "../session/session-service";
7
7
  import type { SessionSource, SessionStatus } from "./common";
@@ -14,9 +14,12 @@ export type ActiveSession = {
14
14
  artifacts?: RootSessionArtifacts;
15
15
  source: SessionSource;
16
16
  startedAt: string;
17
+ status: SessionStatus;
18
+ endedAt?: string | null;
19
+ exitCode?: number | null;
17
20
  pendingPrompt?: string;
18
21
  runtime: BuiltRuntime;
19
- agent: Agent;
22
+ agent: SessionRuntime;
20
23
  started: boolean;
21
24
  aborting: boolean;
22
25
  interactive: boolean;