@cline/core 0.0.69 → 0.0.70

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 (32) hide show
  1. package/dist/extensions/config/runtime-commands.d.ts +1 -0
  2. package/dist/extensions/context/compaction.d.ts +8 -0
  3. package/dist/extensions/index.d.ts +1 -1
  4. package/dist/extensions/plugin/plugin-config-loader.d.ts +1 -1
  5. package/dist/extensions/tools/command-guard-extension.d.ts +22 -0
  6. package/dist/extensions/tools/command-guard.d.ts +29 -0
  7. package/dist/extensions/tools/index.d.ts +1 -0
  8. package/dist/extensions/tools/presets.d.ts +4 -2
  9. package/dist/hub/client/session-client.d.ts +2 -0
  10. package/dist/hub/daemon/entry.js +180 -177
  11. package/dist/hub/index.js +171 -168
  12. package/dist/hub/server/handlers/connector-handlers.d.ts +8 -0
  13. package/dist/index.d.ts +6 -3
  14. package/dist/index.js +176 -173
  15. package/dist/runtime/host/local/agent-event-bridge.d.ts +11 -0
  16. package/dist/runtime/host/runtime-host.d.ts +17 -0
  17. package/dist/runtime/orchestration/session-runtime-orchestrator.d.ts +15 -0
  18. package/dist/services/connectors/connector-child-env.d.ts +14 -0
  19. package/dist/services/connectors/connector-cleanup.d.ts +20 -0
  20. package/dist/services/connectors/connector-supervisor.d.ts +134 -0
  21. package/dist/services/connectors/daemon-connector-reconnect.d.ts +12 -27
  22. package/dist/services/global-settings.d.ts +9 -0
  23. package/dist/services/llms/apihandler-agent-model-adapter.d.ts +1 -1
  24. package/dist/services/providers/local-provider-registry.d.ts +2 -6
  25. package/dist/services/session-data.d.ts +11 -1
  26. package/dist/services/telemetry/core-events.d.ts +19 -1
  27. package/dist/services/telemetry/index.js +1 -1
  28. package/dist/session/history-origin.d.ts +19 -0
  29. package/dist/session/models/session-row.d.ts +4 -0
  30. package/dist/session/stores/session-manifest-store.d.ts +10 -2
  31. package/dist/types/config.d.ts +7 -1
  32. package/package.json +4 -4
@@ -20,7 +20,18 @@ export interface AgentEventBridgeDeps {
20
20
  export declare class AgentEventBridge {
21
21
  private readonly deps;
22
22
  constructor(deps: AgentEventBridgeDeps);
23
+ /**
24
+ * Last agent identity stamped on each session's events while the session
25
+ * was still registered. A session's agent can keep emitting after the host
26
+ * removes it from the sessions map (teardown deletes the entry before the
27
+ * run fully drains), and without this snapshot those late events reach
28
+ * telemetry with no agent identity at all. Bounded FIFO so a long-lived
29
+ * host doesn't accumulate entries forever.
30
+ */
31
+ private readonly lastKnownIdentityBySession;
32
+ private static readonly MAX_IDENTITY_SNAPSHOTS;
23
33
  dispatchAgentEvent(sessionId: string, config: CoreSessionConfig, event: AgentEvent): void;
34
+ private rememberSessionIdentity;
24
35
  handleTeamEvent(rootSessionId: string, event: TeamEvent): Promise<void>;
25
36
  handlePluginEvent(rootSessionId: string, event: {
26
37
  name: string;
@@ -18,6 +18,20 @@ export declare class SessionNotFoundError extends Error {
18
18
  constructor(sessionId?: string | undefined, message?: string);
19
19
  }
20
20
  export declare function isSessionNotFoundError(error: unknown): error is SessionNotFoundError;
21
+ /**
22
+ * A session that cannot serve another turn, whatever the caller does with it.
23
+ *
24
+ * Two distinct causes, one remedy: the session is gone (`session_not_found`,
25
+ * after a hub restart, a deletion, or retention cleanup), or its runtime is stuck
26
+ * with a run that never drained (`session_run_in_progress`). A caller holding a
27
+ * long-lived mapping to that session — a connector thread, for instance — has to
28
+ * replace the session rather than keep retrying against it.
29
+ *
30
+ * Errors reaching a connector have crossed the hub's JSON boundary, so the code
31
+ * may be gone and only the message survives; both are checked, which also keeps
32
+ * this working when the hub and the CLI are different versions.
33
+ */
34
+ export declare function isUnusableSessionError(error: unknown): boolean;
21
35
  type LocalOnlyCoreSessionConfigKeys = "hooks" | "logger" | "telemetry" | "extensionContext" | "extraTools" | "extensions" | "onTeamEvent" | "onConsecutiveMistakeLimitReached";
22
36
  export type RuntimeSessionConfig = Omit<CoreSessionConfig, LocalOnlyCoreSessionConfigKeys | "checkpoint" | "compaction"> & {
23
37
  checkpoint?: Omit<NonNullable<CoreSessionConfig["checkpoint"]>, "createCheckpoint">;
@@ -49,7 +63,10 @@ export interface LocalRuntimeStartOptions {
49
63
  }
50
64
  export interface StartSessionInput {
51
65
  config: StartSessionConfig;
66
+ /** The process/client that starts the session. E.g., "vscode", "cli". */
52
67
  source?: SessionSource;
68
+ /** How the session was initiated, such as user, automation, or subagent. */
69
+ mode?: string;
53
70
  prompt?: string;
54
71
  interactive?: boolean;
55
72
  sessionMetadata?: Record<string, unknown>;
@@ -23,6 +23,21 @@ import { createAgentRuntime } from "@cline/agents";
23
23
  import { type AgentConfig, type AgentEvent, type AgentExtensionRegistry, type AgentResult, type AgentTool, type BasicLogger, type ITelemetryService, type Message, type MessageWithMetadata } from "@cline/shared";
24
24
  import { MessageBuilder } from "../../session/services/message-builder";
25
25
  import { type ConnectionUpdate } from "../config/connection-update";
26
+ export declare const SESSION_RUN_IN_PROGRESS_ERROR_CODE = "session_run_in_progress";
27
+ /**
28
+ * A session was asked to shut down while one of its runs was still in flight and
29
+ * no abort had been requested.
30
+ *
31
+ * Carries a code so callers can recognise it structurally after it crosses the
32
+ * hub's JSON boundary, where an `Error` arrives as a bare message. Connectors use
33
+ * it to tell "this thread's session is unusable" apart from a genuine run failure,
34
+ * and to recover by starting a fresh session instead of wedging the thread.
35
+ */
36
+ export declare class SessionRunInProgressError extends Error {
37
+ readonly agentId?: string | undefined;
38
+ readonly code = "session_run_in_progress";
39
+ constructor(agentId?: string | undefined);
40
+ }
26
41
  /**
27
42
  * Listener invoked for every legacy `AgentEvent` produced by the
28
43
  * session runtime. Use `subscribeEvents(listener)` — it returns an
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Environment for a CLI process the hub daemon launches.
3
+ *
4
+ * The daemon inherits the environment of whichever connector spawned it, and
5
+ * those inherited markers are actively harmful downstream: the daemon sentinel
6
+ * would make the child try to become a hub, and a child marker tells a connector
7
+ * "you are already the detached child", which makes it skip its own
8
+ * already-running check and start alongside a live instance holding the same
9
+ * credentials.
10
+ */
11
+ export declare function buildConnectorChildEnv(env?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
12
+ export declare const __test__: {
13
+ CONNECTOR_CHILD_MARKER_PATTERN: RegExp;
14
+ };
@@ -0,0 +1,20 @@
1
+ import { spawn } from "node:child_process";
2
+ import { type ConnectorCliLaunchSpec } from "@cline/shared";
3
+ export interface CleanupConnectorInstanceOptions {
4
+ launchSpec?: ConnectorCliLaunchSpec | undefined;
5
+ spawnProcess?: typeof spawn;
6
+ timeoutMs?: number;
7
+ }
8
+ /**
9
+ * Reap one dead connector instance through the CLI.
10
+ *
11
+ * What has to be cleaned up — the process state file, thread→session bindings,
12
+ * and the hub sessions the connector owned — is all connector-specific knowledge
13
+ * that lives in the CLI's adapters. Rather than duplicate those conventions in
14
+ * the hub, the supervisor shells back into the CLI's own stop path, which
15
+ * already does exactly this for a process that is no longer running.
16
+ *
17
+ * `--cleanup-instance` deliberately preserves the autostart record: the instance
18
+ * died, it was not retired, so the supervisor still intends to restart it.
19
+ */
20
+ export declare function cleanupConnectorInstanceViaCli(channel: string, instanceId: string, options?: CleanupConnectorInstanceOptions): Promise<void>;
@@ -0,0 +1,134 @@
1
+ import { spawn } from "node:child_process";
2
+ import { type ConnectorCliLaunchSpec, type ConnectorStartRequest, type ConnectorStartResult, type SupervisedConnectorRecord } from "@cline/shared";
3
+ import { listActiveConnectors } from "./active-connectors";
4
+ export declare const RESTART_BASE_DELAY_MS = 1000;
5
+ export declare const RESTART_MAX_DELAY_MS = 60000;
6
+ /** Consecutive failed restarts before the hub stops trying. */
7
+ export declare const RESTART_GIVE_UP_AFTER = 5;
8
+ /**
9
+ * A run that lasts this long is treated as healthy, clearing the restart
10
+ * counter. Without it a connector that stays up for hours and then dies would
11
+ * inherit stale failures and be given up on immediately.
12
+ */
13
+ export declare const RESTART_COUNTER_RESET_MS = 60000;
14
+ /** How often adopted connectors (no child handle) are checked for liveness. */
15
+ export declare const ADOPTED_POLL_INTERVAL_MS = 5000;
16
+ /** How long a stop waits for SIGTERM to land before escalating to SIGKILL. */
17
+ export declare const STOP_SIGTERM_TIMEOUT_MS = 5000;
18
+ /** How long a stop waits for SIGKILL to land before giving up on the wait. */
19
+ export declare const STOP_SIGKILL_TIMEOUT_MS = 2000;
20
+ export interface ConnectorSupervisorDeps {
21
+ launchSpec?: () => ConnectorCliLaunchSpec | undefined;
22
+ spawnProcess?: typeof spawn;
23
+ isProcessRunning?: (pid: number) => boolean;
24
+ killProcess?: (pid: number, signal: NodeJS.Signals) => void;
25
+ listActive?: typeof listActiveConnectors;
26
+ /**
27
+ * Reap a dead instance's leftovers: state file, thread bindings and hub
28
+ * sessions. Delegated because all of that is connector-specific and owned by
29
+ * the CLI; the supervisor only knows a process died.
30
+ */
31
+ cleanupInstance?: (channel: string, instanceId: string) => Promise<void>;
32
+ isAutostartEnabled?: (channel: string, instanceId: string) => boolean;
33
+ log?: (message: string) => void;
34
+ now?: () => number;
35
+ setTimer?: (callback: () => void, delayMs: number) => unknown;
36
+ clearTimer?: (handle: unknown) => void;
37
+ }
38
+ /**
39
+ * Owns the lifecycle of connector processes on behalf of the hub.
40
+ *
41
+ * Three responsibilities, in order of why this exists:
42
+ *
43
+ * 1. **Single instance per (channel, instanceId).** The in-memory map is the
44
+ * authority, so two connectors can never hold the same bot token because two
45
+ * processes raced on a state file.
46
+ * 2. **Reaping.** When a connector dies its state file, thread bindings and hub
47
+ * sessions would otherwise linger until the next manual start, leaving
48
+ * Slack threads bound to sessions that no longer exist.
49
+ * 3. **Restart with backoff.** Replaces external watchdogs, and refuses to
50
+ * spin forever on a connector that cannot start (a revoked token).
51
+ *
52
+ * Connectors are spawned detached so a hub restart does not take them down; a
53
+ * later hub adopts the survivors by pid from their state files. That is why exit
54
+ * detection has two paths: child events for processes this hub spawned, pid
55
+ * polling for adopted ones.
56
+ */
57
+ export declare class ConnectorSupervisor {
58
+ private readonly entries;
59
+ /**
60
+ * Tail of the in-flight start/stop chain per instance key. `start` suspends
61
+ * on `stop` (which shells into the CLI for cleanup, taking seconds), and two
62
+ * unserialised starts interleaving across that suspension each spawn their
63
+ * own process — the map ends up tracking one while the other survives as an
64
+ * untracked ghost holding the connector's credentials and ports.
65
+ */
66
+ private readonly instanceLocks;
67
+ private pollTimer;
68
+ private disposed;
69
+ private readonly launchSpec;
70
+ private readonly spawnProcess;
71
+ private readonly isProcessRunning;
72
+ private readonly killProcess;
73
+ private readonly listActive;
74
+ private readonly cleanupInstance?;
75
+ private readonly isAutostartEnabled;
76
+ private readonly log;
77
+ private readonly now;
78
+ private readonly setTimer;
79
+ private readonly clearTimer;
80
+ constructor(deps?: ConnectorSupervisorDeps);
81
+ /**
82
+ * Take over connectors that are already running, so a replacement hub reaps
83
+ * and restarts the processes it inherited instead of ignoring them.
84
+ */
85
+ adoptRunningConnectors(): SupervisedConnectorRecord[];
86
+ /**
87
+ * Serialise start/stop work per instance key. Both operations suspend
88
+ * mid-flight — a stop waits for the process to die and for the CLI cleanup,
89
+ * a start may embed a stop — and interleaving two of them across those
90
+ * suspensions is how the map ends up tracking one process while another
91
+ * lives on untracked. One instance, one queue.
92
+ */
93
+ private withInstanceLock;
94
+ start(request: ConnectorStartRequest): Promise<ConnectorStartResult>;
95
+ private startLocked;
96
+ stop(request: {
97
+ channel: string;
98
+ instanceId: string;
99
+ disableAutostart?: boolean;
100
+ }): Promise<boolean>;
101
+ private stopLocked;
102
+ private signal;
103
+ private waitForProcessExit;
104
+ list(): SupervisedConnectorRecord[];
105
+ /**
106
+ * Stop supervising without touching the processes: they are detached and
107
+ * outlive this hub on purpose, and the next hub adopts them.
108
+ */
109
+ dispose(): void;
110
+ private spawnEntry;
111
+ private handleExit;
112
+ private scheduleRestart;
113
+ /**
114
+ * An adopted connector has no argv of its own here, so its restart arguments
115
+ * come from the persisted autostart record.
116
+ */
117
+ private resolveRestartArgs;
118
+ private cancelRestart;
119
+ private runCleanup;
120
+ private isEntryAlive;
121
+ /**
122
+ * Adopted connectors have no child handle, so their death is only visible by
123
+ * polling. Processes this hub spawned report their own exit and are skipped.
124
+ */
125
+ private ensurePolling;
126
+ private hasAdoptedRunning;
127
+ private toRecord;
128
+ }
129
+ /**
130
+ * The hub daemon's supervisor. Hub command handlers reach it through here
131
+ * because they are invoked per-request and have no other shared state.
132
+ */
133
+ export declare function setActiveConnectorSupervisor(supervisor: ConnectorSupervisor | undefined): void;
134
+ export declare function getActiveConnectorSupervisor(): ConnectorSupervisor | undefined;
@@ -1,30 +1,15 @@
1
- import { type ConnectorCliLaunchSpec } from "@cline/shared";
2
1
  import { type ReconnectAttempt } from "./connector-autostart";
3
- type ConnectorCliChild = {
4
- stderr?: {
5
- setEncoding: (encoding: string) => void;
6
- on: (event: "data", listener: (chunk: unknown) => void) => void;
7
- };
8
- once: (event: "error" | "close", listener: (value: unknown) => void) => void;
9
- };
10
- type SpawnConnectorCli = (launcher: string, args: string[], options: {
11
- cwd: string;
12
- env: NodeJS.ProcessEnv;
13
- stdio: ["ignore", "ignore", "pipe"];
14
- windowsHide: boolean;
15
- }) => ConnectorCliChild;
16
- declare function runConnectorCli(spec: ConnectorCliLaunchSpec, channel: string, args: string[], options: {
17
- restartInstanceId?: string;
18
- log: (message: string) => void;
19
- spawnProcess?: SpawnConnectorCli;
20
- }): Promise<boolean>;
2
+ import type { ConnectorSupervisor } from "./connector-supervisor";
21
3
  /**
22
- * Restore connectors from the daemon entrypoint through a host-provided CLI
23
- * launch specification. This keeps connector implementations in the CLI app
24
- * while allowing the package-owned daemon entrypoint to supervise recovery.
4
+ * Bring persisted connectors back under the new hub's supervision.
5
+ *
6
+ * Called once per daemon boot, after the supervisor has adopted whatever
7
+ * survived the previous hub. Survivors still have to be *restarted* rather than
8
+ * left running: their hub client authenticated against the old hub's token and
9
+ * cannot re-authenticate against this one, so the process has to come back to
10
+ * attach to the new session.
11
+ *
12
+ * Spawning itself belongs to the supervisor, which is the single authority on
13
+ * how many processes may hold one connector's credentials.
25
14
  */
26
- export declare function reconnectDaemonConnectors(log?: (message: string) => void): Promise<ReconnectAttempt[]>;
27
- export declare const __test__: {
28
- runConnectorCli: typeof runConnectorCli;
29
- };
30
- export {};
15
+ export declare function reconnectDaemonConnectors(log?: (message: string) => void, supervisor?: ConnectorSupervisor | undefined): Promise<ReconnectAttempt[]>;
@@ -25,6 +25,7 @@ export declare const GlobalSettingsSchema: z.ZodPipe<z.ZodObject<{
25
25
  act: "act";
26
26
  }>>>;
27
27
  toolAutoApprove: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
28
+ tuiTheme: z.ZodCatch<z.ZodOptional<z.ZodString>>;
28
29
  disabledTools: z.ZodOptional<z.ZodPipe<z.ZodPreprocess<z.ZodOptional<z.ZodArray<z.ZodString>>>, z.ZodTransform<string[] | undefined, string[] | undefined>>>;
29
30
  disabledPlugins: z.ZodOptional<z.ZodPipe<z.ZodPreprocess<z.ZodOptional<z.ZodArray<z.ZodString>>>, z.ZodTransform<string[] | undefined, string[] | undefined>>>;
30
31
  }, z.core.$strip>, z.ZodTransform<{
@@ -34,6 +35,7 @@ export declare const GlobalSettingsSchema: z.ZodPipe<z.ZodObject<{
34
35
  compactionEnabled?: boolean;
35
36
  planActMode?: GlobalPlanActMode;
36
37
  toolAutoApprove?: boolean;
38
+ tuiTheme?: string;
37
39
  disabledTools?: string[];
38
40
  disabledPlugins?: string[];
39
41
  }, {
@@ -43,6 +45,7 @@ export declare const GlobalSettingsSchema: z.ZodPipe<z.ZodObject<{
43
45
  compactionEnabled?: boolean | undefined;
44
46
  planActMode?: "plan" | "act" | undefined;
45
47
  toolAutoApprove?: boolean | undefined;
48
+ tuiTheme?: string | undefined;
46
49
  disabledTools?: string[] | undefined;
47
50
  disabledPlugins?: string[] | undefined;
48
51
  }>>;
@@ -71,6 +74,12 @@ export declare function setCompactionModeGlobally(mode: GlobalCompactionMode): v
71
74
  export declare function readPlanActModeGlobally(): GlobalPlanActMode | undefined;
72
75
  export declare function setPlanActModeGlobally(planActMode: GlobalPlanActMode): void;
73
76
  export declare function readToolAutoApproveGlobally(): boolean | undefined;
77
+ /**
78
+ * Returns the persisted TUI theme id, or undefined when the user never chose
79
+ * one (callers apply their own default, typically terminal auto-detection).
80
+ */
81
+ export declare function readTuiThemeGlobally(): string | undefined;
82
+ export declare function setTuiThemeGlobally(tuiTheme: string): void;
74
83
  export declare function setToolAutoApproveGlobally(toolAutoApprove: boolean): void;
75
84
  export declare function resolveDisabledToolNames(disabledToolNames?: ReadonlyArray<string>): Set<string>;
76
85
  export declare function resolveDisabledPluginPaths(disabledPluginPaths?: ReadonlyArray<string>): Set<string>;
@@ -12,7 +12,7 @@
12
12
  * This is the inverse of the gateway's `toApiStreamChunk` in
13
13
  * `@cline/llms` `compat.ts`.
14
14
  */
15
- import type { ApiHandler } from "@cline/llms";
15
+ import { type ApiHandler } from "@cline/llms";
16
16
  import type { AgentModel } from "@cline/shared";
17
17
  /**
18
18
  * Resolves the `ApiHandler` to delegate to. A function is supported (and may be
@@ -1,4 +1,4 @@
1
- import { type ProviderModel } from "@cline/shared";
1
+ import { type ModelInfo, type ProviderModel } from "@cline/shared";
2
2
  import { z } from "zod";
3
3
  import type { ProviderSettings, StoredProviderSettings } from "../../types/provider-settings";
4
4
  import type { ProviderSettingsManager } from "../storage/provider-settings-manager";
@@ -244,11 +244,7 @@ export declare function readModelsFileSync(filePath: string): StoredModelsFile;
244
244
  export declare function readModelsFile(filePath: string): Promise<StoredModelsFile>;
245
245
  export declare function writeModelsFileSync(filePath: string, state: StoredModelsFile): void;
246
246
  export declare function writeModelsFile(filePath: string, state: StoredModelsFile): Promise<void>;
247
- export declare function toProviderModel(modelId: string, info: {
248
- name?: string;
249
- capabilities?: string[];
250
- thinkingConfig?: unknown;
251
- }): ProviderModel;
247
+ export declare function toProviderModel(modelId: string, info: Pick<ModelInfo, "name" | "contextWindow" | "capabilities" | "thinkingConfig">): ProviderModel;
252
248
  export declare function registerProviderSettingsProvider(settings: ProviderSettings): void;
253
249
  export declare function registerConfiguredProvidersFromSettings(state: StoredProviderSettings): void;
254
250
  /**
@@ -23,8 +23,17 @@ export type MessagesFileContext = {
23
23
  agent: "lead" | "subagent" | "teammate";
24
24
  sessionId: string;
25
25
  taskType?: string;
26
+ origin: {
27
+ source: string;
28
+ mode: string;
29
+ sessionId: string;
30
+ parentThreadId?: string;
31
+ subagent?: string;
32
+ version?: string;
33
+ trigger?: string;
34
+ };
26
35
  };
27
- export declare function resolveMessagesFileContext(sessionId: string): MessagesFileContext;
36
+ export declare function resolveMessagesFileContext(row: SessionRow): MessagesFileContext;
28
37
  export declare function buildMessagesFilePayload(input: {
29
38
  updatedAt: string;
30
39
  context: MessagesFileContext;
@@ -36,6 +45,7 @@ export declare function buildMessagesFilePayload(input: {
36
45
  agent: "lead" | "subagent" | "teammate";
37
46
  sessionId: string;
38
47
  taskType?: string;
48
+ origin: MessagesFileContext["origin"];
39
49
  messages: StoredMessageWithMetadata[];
40
50
  system_prompt?: string;
41
51
  };
@@ -73,6 +73,7 @@ export declare const CORE_TELEMETRY_EVENTS: {
73
73
  readonly SDK: {
74
74
  readonly ERROR: "sdk.error";
75
75
  readonly TOOL_TIMEOUT: "sdk.tool_timeout";
76
+ readonly PLAN_MODE_COMMAND_BLOCKED: "sdk.plan_mode_command_blocked";
76
77
  };
77
78
  readonly FEATURE_FLAGS: {
78
79
  readonly FLAG_CALLED: "$feature_flag_called";
@@ -272,6 +273,21 @@ export declare function captureMistakeLimitReached(telemetry: ITelemetryService
272
273
  maxConsecutiveMistakes: number;
273
274
  } & Partial<TelemetryAgentIdentityProperties>): void;
274
275
  export declare function captureRunCommandsTimeout(telemetry: ITelemetryService | undefined, properties: RunCommandsTimeoutTelemetryProperties): void;
276
+ export interface PlanModeCommandBlockedTelemetryProperties {
277
+ tool_name: "run_commands";
278
+ /**
279
+ * Short description of the blocked construct (e.g. "`rm`", "`sed -i`
280
+ * (in-place edit)"). Never contains raw command content.
281
+ */
282
+ blocked_construct: string;
283
+ command_count: number;
284
+ agent_id?: string;
285
+ conversation_id?: string;
286
+ run_id?: string;
287
+ iteration?: number;
288
+ tool_call_id?: string;
289
+ }
290
+ export declare function capturePlanModeCommandBlocked(telemetry: ITelemetryService | undefined, properties: PlanModeCommandBlockedTelemetryProperties): void;
275
291
  export declare function captureMentionUsed(telemetry: ITelemetryService | undefined, mentionType: "file" | "folder" | "url" | "problems" | "terminal" | "git-changes" | "commit", contentLength?: number): void;
276
292
  export declare function captureMentionFailed(telemetry: ITelemetryService | undefined, mentionType: "file" | "folder" | "url" | "problems" | "terminal" | "git-changes" | "commit", errorType: "not_found" | "permission_denied" | "network_error" | "parse_error" | "unknown", errorMessage?: string): void;
277
293
  export declare function captureMentionSearchResults(telemetry: ITelemetryService | undefined, query: string, resultCount: number, searchType: "file" | "folder" | "all", isEmpty: boolean): void;
@@ -316,8 +332,10 @@ export type TelemetryCompactionStrategy = "basic" | "agentic" | "custom";
316
332
  * - `auto` — fired automatically by `createContextCompactionPrepareTurn`
317
333
  * when input tokens reach the fixed compaction threshold.
318
334
  * - `manual` — user-initiated (e.g. CLI `/compact`).
335
+ * - `overflow_recovery` — forced by the runtime after a provider rejected
336
+ * the request as exceeding the model's context window.
319
337
  */
320
- export type TelemetryCompactionMode = "auto" | "manual";
338
+ export type TelemetryCompactionMode = "auto" | "manual" | "overflow_recovery";
321
339
  export interface CaptureCompactionExecutedProperties {
322
340
  ulid: string;
323
341
  strategy: TelemetryCompactionStrategy;
@@ -1 +1 @@
1
- import{existsSync as D,mkdirSync as G,readFileSync as v,writeFileSync as u}from"node:fs";import{resolve as x}from"node:path";import{resolveSessionDataDir as b}from"@cline/shared/storage";import{nanoid as S}from"nanoid";import*as m from"node-machine-id";var c="machine-id",h,w=!1;function Y(){if(!w)h=E(),w=!0;return h??k()}function L(f){let O=f?.trim();if(O)return O;let P=E();if(P)return P;return k()}function d(){let f=m;return f.machineIdSync??f.default?.machineIdSync}function E(){try{let f=d();if(!f)return;return f().trim()||void 0}catch{return}}function k(){let f=b(),O=x(f,c);try{if(D(O)){let T=v(O,"utf8").trim();if(T.length>0)return T}}catch{}let P=`cl-${S()}`;try{G(f,{recursive:!0}),u(O,P,"utf8")}catch{}return P}class M{name;metadata;meter;logger;enabled;distinctId;commonProperties;counters=new Map;histograms=new Map;gauges=new Map;gaugeValues=new Map;meterProvider;loggerProvider;constructor(f){this.name=f.name??"OpenTelemetryAdapter",this.metadata={...f.metadata},this.meterProvider=f.meterProvider,this.loggerProvider=f.loggerProvider,this.meter=f.meterProvider?.getMeter("cline")??null,this.logger=f.loggerProvider?.getLogger("cline")??null,this.enabled=f.enabled??!0,this.distinctId=f.distinctId,this.commonProperties=f.commonProperties?{...f.commonProperties}:{}}emit(f,O){if(!this.isEnabled())return;this.emitLog(f,O,!1)}emitRequired(f,O){this.emitLog(f,O,!0)}recordCounter(f,O,P,T,A=!1){if(!this.meter||!A&&!this.isEnabled())return;let j=this.counters.get(f);if(!j)j=this.meter.createCounter(f,T?{description:T}:void 0),this.counters.set(f,j);j.add(O,this.flattenProperties(this.buildAttributes(P)))}recordHistogram(f,O,P,T,A=!1){if(!this.meter||!A&&!this.isEnabled())return;let j=this.histograms.get(f);if(!j)j=this.meter.createHistogram(f,T?{description:T}:void 0),this.histograms.set(f,j);j.record(O,this.flattenProperties(this.buildAttributes(P)))}recordGauge(f,O,P,T,A=!1){if(!this.meter||!A&&!this.isEnabled())return;let j=this.buildAttributes(P),$=JSON.stringify(j),W=this.gaugeValues.get(f);if(O===null){if(W){if(W.delete($),W.size===0)this.gaugeValues.delete(f),this.gauges.delete(f)}return}let H=W;if(!H)H=new Map,this.gaugeValues.set(f,H);if(!this.gauges.has(f)){let J=this.meter.createObservableGauge(f,T?{description:T}:void 0);J.addCallback((X)=>{for(let U of this.snapshotGaugeSeries(f))X.observe(U.value,this.flattenProperties(U.attributes))}),this.gauges.set(f,J)}H.set($,{value:O,attributes:j})}isEnabled(){return typeof this.enabled==="function"?this.enabled():this.enabled}setDistinctId(f){this.distinctId=f}setCommonProperties(f){this.commonProperties={...f}}updateCommonProperties(f){this.commonProperties={...this.commonProperties,...f}}async flush(){await Promise.all([this.meterProvider?.forceFlush?.(),this.loggerProvider?.forceFlush?.()])}async dispose(){await Promise.all([this.meterProvider?.shutdown?.(),this.loggerProvider?.shutdown?.()])}emitLog(f,O,P){if(!this.logger)return;let T=this.flattenProperties(this.buildAttributes(O,P));this.logger.emit({severityText:"INFO",body:f,attributes:T})}buildAttributes(f,O=!1){return{...this.commonProperties,...this.metadata,...f,...this.distinctId?{distinct_id:this.distinctId}:{},...O?{_required:!0}:{}}}snapshotGaugeSeries(f){let O=this.gaugeValues.get(f);if(!O)return[];return Array.from(O.values(),(P)=>({value:P.value,attributes:P.attributes?{...P.attributes}:void 0}))}flattenProperties(f,O="",P=new WeakSet,T=0){if(!f)return{};let A={},j=100,$=10;for(let[W,H]of Object.entries(f)){if(W==="__proto__"||W==="constructor"||W==="prototype")continue;let J=O?`${O}.${W}`:W;if(H===null||H===void 0){A[J]=String(H);continue}if(Array.isArray(H)){let X=H.length>j?H.slice(0,j):H;try{A[J]=JSON.stringify(X)}catch{A[J]="[UnserializableArray]"}if(H.length>j)A[`${J}_truncated`]=!0,A[`${J}_original_length`]=H.length;continue}if(typeof H==="object"){if(H instanceof Date){A[J]=H.toISOString();continue}if(H instanceof Error){A[J]=H.message;continue}if(P.has(H)){A[J]="[Circular]";continue}if(T>=$){A[J]="[MaxDepthExceeded]";continue}P.add(H),Object.assign(A,this.flattenProperties(H,J,P,T+1));continue}if(l(H)){A[J]=H;continue}try{A[J]=JSON.stringify(H)}catch{A[J]=String(H)}}return A}}function l(f){return typeof f==="string"||typeof f==="number"||typeof f==="boolean"}import{metrics as ff,trace as Of}from"@opentelemetry/api";import{logs as Pf}from"@opentelemetry/api-logs";import{OTLPLogExporter as Tf}from"@opentelemetry/exporter-logs-otlp-http";import{OTLPMetricExporter as Af}from"@opentelemetry/exporter-metrics-otlp-http";import{OTLPTraceExporter as jf}from"@opentelemetry/exporter-trace-otlp-http";import{resourceFromAttributes as Hf}from"@opentelemetry/resources";import{BatchLogRecordProcessor as $f,ConsoleLogRecordExporter as Jf,LoggerProvider as Wf}from"@opentelemetry/sdk-logs";import{ConsoleMetricExporter as Kf,MeterProvider as Lf,PeriodicExportingMetricReader as N}from"@opentelemetry/sdk-metrics";import{BatchSpanProcessor as Mf,ConsoleSpanExporter as Rf,SimpleSpanProcessor as Vf}from"@opentelemetry/sdk-trace-base";import{NodeTracerProvider as Xf}from"@opentelemetry/sdk-trace-node";import{ATTR_SERVICE_NAME as Yf,ATTR_SERVICE_VERSION as Zf}from"@opentelemetry/semantic-conventions";import{mkdirSync as mf,readFileSync as r,statSync as a,writeFileSync as cf}from"node:fs";import{resolveGlobalSettingsPath as n}from"@cline/shared/storage";import{z as K}from"zod";import{AGENT_UNEXPECTED_REASONING_TOKENS_EVENT as If,captureAgentUnexpectedReasoningTokens as Nf,captureTaskLifecycleEvent as yf,SDK_ERROR_TELEMETRY_EVENT as zf,TASK_CANCELLED_EVENT as gf,TASK_FIRST_CHUNK_RECEIVED_EVENT as Df,TASK_PROVIDER_REQUEST_STARTED_EVENT as Gf,TASK_PROVIDER_STREAM_FAILED_EVENT as vf,TASK_PROVIDER_STREAM_STARTED_EVENT as uf}from"@cline/shared";var C=K.preprocess((f)=>Array.isArray(f)?f.filter((O)=>typeof O==="string").map((O)=>O.trim()).filter(Boolean):void 0,K.array(K.string()).optional()).transform((f)=>{if(!f)return;let O=[...new Set(f)].sort((P,T)=>P.localeCompare(T));return O.length>0?O:void 0}),p=K.enum(["basic","agentic"]).catch("agentic"),i=K.enum(["plan","act"]),q=K.object({telemetryOptOut:K.boolean().default(!1).catch(!1),autoUpdateEnabled:K.boolean().default(!0).catch(!0),compactionStrategy:p.optional(),compactionEnabled:K.boolean().optional().catch(void 0),planActMode:i.optional().catch(void 0),toolAutoApprove:K.boolean().optional().catch(void 0),disabledTools:C.optional(),disabledPlugins:C.optional()}).strip().transform((f)=>{let O={autoUpdateEnabled:f.autoUpdateEnabled,telemetryOptOut:f.telemetryOptOut};if(f.compactionStrategy)O.compactionStrategy=f.compactionStrategy;if(f.compactionEnabled!==void 0)O.compactionEnabled=f.compactionEnabled;if(f.planActMode)O.planActMode=f.planActMode;if(f.toolAutoApprove!==void 0)O.toolAutoApprove=f.toolAutoApprove;if(f.disabledTools?.length)O.disabledTools=f.disabledTools;if(f.disabledPlugins?.length)O.disabledPlugins=f.disabledPlugins;return O});function R(){return q.parse({})}var Z;function s(f){if(f.disabledTools)Object.freeze(f.disabledTools);if(f.disabledPlugins)Object.freeze(f.disabledPlugins);return Object.freeze(f)}function o(f){let O;try{O=r(f,"utf8")}catch{return R()}try{let P=q.safeParse(JSON.parse(O));return P.success?P.data:R()}catch{return R()}}function t(){let f=n(),O=a(f,{throwIfNoEntry:!1}),P=O?.mtimeMs??0,T=O?.size??0,A=Z;if(A&&A.path===f&&A.mtimeMs===P&&A.size===T)return A;let j=s(O?o(f):R());return Z={path:f,mtimeMs:P,size:T,value:j},Z}function e(){return t().value}function I(){return e().telemetryOptOut}class _{name;logger;enabled;constructor(f={}){this.name=f.name??"TelemetryLoggerSink",this.logger=f.logger,this.enabled=f.enabled??!0}emit(f,O){if(!this.isEnabled())return;this.logger?.log("telemetry.event",{telemetrySink:this.name,event:f,properties:O})}emitRequired(f,O){this.logger?.log("telemetry.required_event",{telemetrySink:this.name,severity:"warn",event:f,properties:O})}recordCounter(f,O,P,T,A){if(!A&&!this.isEnabled())return;this.logger?.debug("telemetry.metric",{telemetrySink:this.name,instrument:"counter",name:f,value:O,attributes:P,description:T,required:A===!0})}recordHistogram(f,O,P,T,A){if(!A&&!this.isEnabled())return;this.logger?.debug("telemetry.metric",{telemetrySink:this.name,instrument:"histogram",name:f,value:O,attributes:P,description:T,required:A===!0})}recordGauge(f,O,P,T,A){if(!A&&!this.isEnabled())return;this.logger?.debug("telemetry.metric",{telemetrySink:this.name,instrument:"gauge",name:f,value:O,attributes:P,description:T,required:A===!0})}isEnabled(){return typeof this.enabled==="function"?this.enabled():this.enabled}async flush(){}async dispose(){}}class V{adapters;metadata;distinctId;deviceId;commonProperties;constructor(f={}){if(this.adapters=[...f.adapters??[]],f.logger)this.adapters.push(new _({logger:f.logger}));this.metadata={...f.metadata??{}},this.distinctId=f.distinctId,this.deviceId=f.deviceId??Y(),this.commonProperties={...f.commonProperties??{}}}addAdapter(f){this.adapters.push(f)}setDistinctId(f){this.distinctId=f}setMetadata(f){this.metadata={...f}}updateMetadata(f){this.metadata={...this.metadata,...f}}setCommonProperties(f){this.commonProperties={...f}}updateCommonProperties(f){this.commonProperties={...this.commonProperties,...f}}isEnabled(){return this.adapters.some((f)=>f.isEnabled())}capture(f){let O=this.buildAttributes(f.properties);for(let P of this.adapters)P.emit(f.event,O)}captureRequired(f,O){let P=this.buildAttributes(O);for(let T of this.adapters)T.emitRequired(f,P)}recordCounter(f,O,P,T,A=!1){let j=this.buildAttributes(P);for(let $ of this.adapters)$.recordCounter(f,O,j,T,A)}recordHistogram(f,O,P,T,A=!1){let j=this.buildAttributes(P);for(let $ of this.adapters)$.recordHistogram(f,O,j,T,A)}recordGauge(f,O,P,T,A=!1){let j=this.buildAttributes(P);for(let $ of this.adapters)$.recordGauge(f,O,j,T,A)}async flush(){await Promise.all(this.adapters.map((f)=>f.flush()))}async dispose(){await Promise.all(this.adapters.map((f)=>f.dispose()))}buildAttributes(f){return{...this.commonProperties,...f,...this.metadata,...this.distinctId?{distinct_id:this.distinctId}:{},device_id:this.deviceId}}}class y{distinctId;metadata;commonProperties;constructor(f={}){this.distinctId=f.distinctId,this.metadata={...f.metadata??{}},this.commonProperties={...f.commonProperties??{}}}setDistinctId(f){this.distinctId=f}setMetadata(f){this.metadata={...f}}updateMetadata(f){this.metadata={...this.metadata,...f}}setCommonProperties(f){this.commonProperties={...f}}updateCommonProperties(f){this.commonProperties={...this.commonProperties,...f}}isEnabled(){return!1}capture(f){this.resolveProperties(f.properties)}captureRequired(f,O){this.resolveProperties(O)}recordCounter(){}recordHistogram(){}recordGauge(){}async flush(){}async dispose(){}resolveProperties(f){return{...this.commonProperties,...f,...this.metadata,...this.distinctId?{distinct_id:this.distinctId}:{}}}}class Q{meterProvider;loggerProvider;tracerProvider;options;constructor(f={}){this.options=f;let O=Hf({[Yf]:f.serviceName??"cline",...f.serviceVersion?{[Zf]:f.serviceVersion}:{}});if(this.meterProvider=this.createMeterProvider(O),this.loggerProvider=this.createLoggerProvider(O),this.tracerProvider=this.createTracerProvider(O),this.meterProvider)ff.setGlobalMeterProvider(this.meterProvider);if(this.loggerProvider)Pf.setGlobalLoggerProvider(this.loggerProvider);if(this.tracerProvider)this.tracerProvider.register()}getTracer(f="cline",O){return Of.getTracer(f,O??this.options.serviceVersion)}createAdapter(f){return new M({...f,meterProvider:this.meterProvider,loggerProvider:this.loggerProvider})}createTelemetryService(f){let O=this.createAdapter({name:f.name,enabled:this.options.enabled,metadata:f.metadata});return new V({...f,adapters:[O],distinctId:L(f.distinctId)})}async forceFlush(){await Promise.all([this.meterProvider?.forceFlush?.(),this.loggerProvider?.forceFlush?.(),this.tracerProvider?.forceFlush?.()])}async dispose(){await Promise.all([this.meterProvider?.shutdown?.(),this.loggerProvider?.shutdown?.(),this.tracerProvider?.shutdown?.()])}createMeterProvider(f){let O=B(this.options.metricsExporter);if(O.length===0)return null;let P=Math.max(1000,this.options.metricExportIntervalMs??this.options.metricExportInterval??60000),T=Math.min(30000,Math.floor(P*0.8)),A=O.map((j)=>Ff(j,{endpoint:this.options.otlpEndpoint,headers:this.options.otlpHeaders,insecure:this.options.otlpInsecure??!1,protocol:"http/json",interval:P,timeout:T})).filter((j)=>j!==null);if(A.length===0)return null;return new Lf({resource:f,readers:A})}createTracerProvider(f){let O=B(this.options.tracesExporter);if(O.length===0)return null;let P=this.options.otlpTracesEndpoint??this.options.otlpEndpoint,T=this.options.otlpTracesHeaders??this.options.otlpHeaders,A=[];for(let j of O){let $=Qf(j,{endpoint:P,headers:T,insecure:this.options.otlpInsecure??!1,protocol:"http/json"});if($)A.push($)}if(A.length===0)return null;return new Xf({resource:f,spanProcessors:A})}createLoggerProvider(f){let O=B(this.options.logsExporter);if(O.length===0)return null;let P=O.map((T)=>{let A=Bf(T,{endpoint:this.options.otlpEndpoint,headers:this.options.otlpHeaders,insecure:this.options.otlpInsecure??!1,protocol:"http/json"});if(!A)return null;return new $f(A,{maxQueueSize:this.options.logMaxQueueSize??2048,maxExportBatchSize:this.options.logBatchSize??512,scheduledDelayMillis:this.options.logBatchTimeoutMs??this.options.logBatchTimeout??5000})}).filter((T)=>T!==null);if(P.length===0)return null;return new Wf({resource:f,processors:P})}}function z(f){let O=new Q(f),P=O.createTelemetryService(f),T=()=>{P.captureRequired("telemetry.provider_created",{provider:"opentelemetry",enabled:f.enabled??!0,logsExporter:Array.isArray(f.logsExporter)?f.logsExporter.join(","):f.logsExporter,metricsExporter:Array.isArray(f.metricsExporter)?f.metricsExporter.join(","):f.metricsExporter,tracesExporter:Array.isArray(f.tracesExporter)?f.tracesExporter.join(","):f.tracesExporter,otlpProtocol:f.otlpProtocol,hasOtlpEndpoint:Boolean(f.otlpEndpoint),serviceName:f.serviceName,serviceVersion:f.serviceVersion})};if(!f.deferProviderCreatedEvent)T();return{provider:O,telemetry:P,emitProviderCreated:T}}function g(f){if(I())return{telemetry:new y(f)};if(f.enabled!==!0)return{telemetry:new V({...f,distinctId:L(f.distinctId)})};return z(f)}function _f(f){let{telemetry:O,provider:P,emitProviderCreated:T}=g(f);return{telemetry:O,provider:P,flush:async()=>{let $=P;if($&&typeof $.forceFlush==="function")try{await $.forceFlush()}catch{}},dispose:async()=>{await Promise.allSettled([O.dispose(),P?.dispose()])},...f.deferProviderCreatedEvent&&T?{emitProviderCreated:T}:{}}}function B(f){if(!f)return[];return(Array.isArray(f)?f:f.split(",")).map((P)=>P.trim()).filter((P)=>P==="console"||P==="otlp")}function Bf(f,O){if(f==="console")return new Jf;if(!O.endpoint)return null;let P=F(O.endpoint,"/v1/logs");return new Tf({url:P,headers:O.headers})}function Qf(f,O){if(f==="console")return new Vf(new Rf);if(!O.endpoint)return null;let P=F(O.endpoint,"/v1/traces");return new Mf(new jf({url:P,headers:O.headers}))}function Ff(f,O){if(f==="console")return new N({exporter:new Kf,exportIntervalMillis:O.interval,exportTimeoutMillis:O.timeout});if(!O.endpoint)return null;let P=F(O.endpoint,"/v1/metrics");return new N({exporter:new Af({url:P,headers:O.headers}),exportIntervalMillis:O.interval,exportTimeoutMillis:O.timeout})}function F(f,O){let P=new URL(f),T=P.pathname.endsWith("/")?P.pathname.slice(0,-1):P.pathname;return P.pathname=T.endsWith(O)?T:`${T}${O}`,P.toString()}export{L as resolveCoreDistinctId,Y as resolveCoreDeviceId,z as createOpenTelemetryTelemetryService,g as createConfiguredTelemetryService,_f as createConfiguredTelemetryHandle,Q as OpenTelemetryProvider,M as OpenTelemetryAdapter};
1
+ import{existsSync as g,mkdirSync as v,readFileSync as x,writeFileSync as G}from"node:fs";import{resolve as u}from"node:path";import{resolveSessionDataDir as b}from"@cline/shared/storage";import{nanoid as S}from"nanoid";import*as m from"node-machine-id";var c="machine-id",k,E=!1;function Z(){if(!E)k=h(),E=!0;return k??C()}function L(f){let P=f?.trim();if(P)return P;let O=h();if(O)return O;return C()}function d(){let f=m;return f.machineIdSync??f.default?.machineIdSync}function h(){try{let f=d();if(!f)return;return f().trim()||void 0}catch{return}}function C(){let f=b(),P=u(f,c);try{if(g(P)){let A=x(P,"utf8").trim();if(A.length>0)return A}}catch{}let O=`cl-${S()}`;try{v(f,{recursive:!0}),G(P,O,"utf8")}catch{}return O}class M{name;metadata;meter;logger;enabled;distinctId;commonProperties;counters=new Map;histograms=new Map;gauges=new Map;gaugeValues=new Map;meterProvider;loggerProvider;constructor(f){this.name=f.name??"OpenTelemetryAdapter",this.metadata={...f.metadata},this.meterProvider=f.meterProvider,this.loggerProvider=f.loggerProvider,this.meter=f.meterProvider?.getMeter("cline")??null,this.logger=f.loggerProvider?.getLogger("cline")??null,this.enabled=f.enabled??!0,this.distinctId=f.distinctId,this.commonProperties=f.commonProperties?{...f.commonProperties}:{}}emit(f,P){if(!this.isEnabled())return;this.emitLog(f,P,!1)}emitRequired(f,P){this.emitLog(f,P,!0)}recordCounter(f,P,O,A,T=!1){if(!this.meter||!T&&!this.isEnabled())return;let j=this.counters.get(f);if(!j)j=this.meter.createCounter(f,A?{description:A}:void 0),this.counters.set(f,j);j.add(P,this.flattenProperties(this.buildAttributes(O)))}recordHistogram(f,P,O,A,T=!1){if(!this.meter||!T&&!this.isEnabled())return;let j=this.histograms.get(f);if(!j)j=this.meter.createHistogram(f,A?{description:A}:void 0),this.histograms.set(f,j);j.record(P,this.flattenProperties(this.buildAttributes(O)))}recordGauge(f,P,O,A,T=!1){if(!this.meter||!T&&!this.isEnabled())return;let j=this.buildAttributes(O),$=JSON.stringify(j),K=this.gaugeValues.get(f);if(P===null){if(K){if(K.delete($),K.size===0)this.gaugeValues.delete(f),this.gauges.delete(f)}return}let H=K;if(!H)H=new Map,this.gaugeValues.set(f,H);if(!this.gauges.has(f)){let J=this.meter.createObservableGauge(f,A?{description:A}:void 0);J.addCallback((Y)=>{for(let U of this.snapshotGaugeSeries(f))Y.observe(U.value,this.flattenProperties(U.attributes))}),this.gauges.set(f,J)}H.set($,{value:P,attributes:j})}isEnabled(){return typeof this.enabled==="function"?this.enabled():this.enabled}setDistinctId(f){this.distinctId=f}setCommonProperties(f){this.commonProperties={...f}}updateCommonProperties(f){this.commonProperties={...this.commonProperties,...f}}async flush(){await Promise.all([this.meterProvider?.forceFlush?.(),this.loggerProvider?.forceFlush?.()])}async dispose(){await Promise.all([this.meterProvider?.shutdown?.(),this.loggerProvider?.shutdown?.()])}emitLog(f,P,O){if(!this.logger)return;let A=this.flattenProperties(this.buildAttributes(P,O));this.logger.emit({severityText:"INFO",body:f,attributes:A})}buildAttributes(f,P=!1){return{...this.commonProperties,...this.metadata,...f,...this.distinctId?{distinct_id:this.distinctId}:{},...P?{_required:!0}:{}}}snapshotGaugeSeries(f){let P=this.gaugeValues.get(f);if(!P)return[];return Array.from(P.values(),(O)=>({value:O.value,attributes:O.attributes?{...O.attributes}:void 0}))}flattenProperties(f,P="",O=new WeakSet,A=0){if(!f)return{};let T={},j=100,$=10;for(let[K,H]of Object.entries(f)){if(K==="__proto__"||K==="constructor"||K==="prototype")continue;let J=P?`${P}.${K}`:K;if(H===null||H===void 0){T[J]=String(H);continue}if(Array.isArray(H)){let Y=H.length>j?H.slice(0,j):H;try{T[J]=JSON.stringify(Y)}catch{T[J]="[UnserializableArray]"}if(H.length>j)T[`${J}_truncated`]=!0,T[`${J}_original_length`]=H.length;continue}if(typeof H==="object"){if(H instanceof Date){T[J]=H.toISOString();continue}if(H instanceof Error){T[J]=H.message;continue}if(O.has(H)){T[J]="[Circular]";continue}if(A>=$){T[J]="[MaxDepthExceeded]";continue}O.add(H),Object.assign(T,this.flattenProperties(H,J,O,A+1));continue}if(l(H)){T[J]=H;continue}try{T[J]=JSON.stringify(H)}catch{T[J]=String(H)}}return T}}function l(f){return typeof f==="string"||typeof f==="number"||typeof f==="boolean"}import{metrics as ff,trace as Pf}from"@opentelemetry/api";import{logs as Of}from"@opentelemetry/api-logs";import{OTLPLogExporter as Af}from"@opentelemetry/exporter-logs-otlp-http";import{OTLPMetricExporter as Tf}from"@opentelemetry/exporter-metrics-otlp-http";import{OTLPTraceExporter as jf}from"@opentelemetry/exporter-trace-otlp-http";import{resourceFromAttributes as Hf}from"@opentelemetry/resources";import{BatchLogRecordProcessor as $f,ConsoleLogRecordExporter as Jf,LoggerProvider as Wf}from"@opentelemetry/sdk-logs";import{ConsoleMetricExporter as Kf,MeterProvider as Lf,PeriodicExportingMetricReader as I}from"@opentelemetry/sdk-metrics";import{BatchSpanProcessor as Mf,ConsoleSpanExporter as Vf,SimpleSpanProcessor as Xf}from"@opentelemetry/sdk-trace-base";import{NodeTracerProvider as Yf}from"@opentelemetry/sdk-trace-node";import{ATTR_SERVICE_NAME as Zf,ATTR_SERVICE_VERSION as _f}from"@opentelemetry/semantic-conventions";import{mkdirSync as mf,readFileSync as r,statSync as a,writeFileSync as cf}from"node:fs";import{resolveGlobalSettingsPath as n}from"@cline/shared/storage";import{z as W}from"zod";import{AGENT_UNEXPECTED_REASONING_TOKENS_EVENT as Nf,captureAgentUnexpectedReasoningTokens as If,captureTaskLifecycleEvent as zf,SDK_ERROR_TELEMETRY_EVENT as yf,TASK_CANCELLED_EVENT as Df,TASK_FIRST_CHUNK_RECEIVED_EVENT as gf,TASK_PROVIDER_REQUEST_STARTED_EVENT as vf,TASK_PROVIDER_STREAM_FAILED_EVENT as xf,TASK_PROVIDER_STREAM_STARTED_EVENT as Gf}from"@cline/shared";var w=W.preprocess((f)=>Array.isArray(f)?f.filter((P)=>typeof P==="string").map((P)=>P.trim()).filter(Boolean):void 0,W.array(W.string()).optional()).transform((f)=>{if(!f)return;let P=[...new Set(f)].sort((O,A)=>O.localeCompare(A));return P.length>0?P:void 0}),p=W.enum(["basic","agentic"]).catch("agentic"),i=W.enum(["plan","act"]),q=W.object({telemetryOptOut:W.boolean().default(!1).catch(!1),autoUpdateEnabled:W.boolean().default(!0).catch(!0),compactionStrategy:p.optional(),compactionEnabled:W.boolean().optional().catch(void 0),planActMode:i.optional().catch(void 0),toolAutoApprove:W.boolean().optional().catch(void 0),tuiTheme:W.string().optional().catch(void 0),disabledTools:w.optional(),disabledPlugins:w.optional()}).strip().transform((f)=>{let P={autoUpdateEnabled:f.autoUpdateEnabled,telemetryOptOut:f.telemetryOptOut};if(f.compactionStrategy)P.compactionStrategy=f.compactionStrategy;if(f.compactionEnabled!==void 0)P.compactionEnabled=f.compactionEnabled;if(f.planActMode)P.planActMode=f.planActMode;if(f.toolAutoApprove!==void 0)P.toolAutoApprove=f.toolAutoApprove;if(f.tuiTheme?.trim())P.tuiTheme=f.tuiTheme.trim();if(f.disabledTools?.length)P.disabledTools=f.disabledTools;if(f.disabledPlugins?.length)P.disabledPlugins=f.disabledPlugins;return P});function V(){return q.parse({})}var _;function s(f){if(f.disabledTools)Object.freeze(f.disabledTools);if(f.disabledPlugins)Object.freeze(f.disabledPlugins);return Object.freeze(f)}function o(f){let P;try{P=r(f,"utf8")}catch{return V()}try{let O=q.safeParse(JSON.parse(P));return O.success?O.data:V()}catch{return V()}}function t(){let f=n(),P=a(f,{throwIfNoEntry:!1}),O=P?.mtimeMs??0,A=P?.size??0,T=_;if(T&&T.path===f&&T.mtimeMs===O&&T.size===A)return T;let j=s(P?o(f):V());return _={path:f,mtimeMs:O,size:A,value:j},_}function e(){return t().value}function N(){return e().telemetryOptOut}class B{name;logger;enabled;constructor(f={}){this.name=f.name??"TelemetryLoggerSink",this.logger=f.logger,this.enabled=f.enabled??!0}emit(f,P){if(!this.isEnabled())return;this.logger?.log("telemetry.event",{telemetrySink:this.name,event:f,properties:P})}emitRequired(f,P){this.logger?.log("telemetry.required_event",{telemetrySink:this.name,severity:"warn",event:f,properties:P})}recordCounter(f,P,O,A,T){if(!T&&!this.isEnabled())return;this.logger?.debug("telemetry.metric",{telemetrySink:this.name,instrument:"counter",name:f,value:P,attributes:O,description:A,required:T===!0})}recordHistogram(f,P,O,A,T){if(!T&&!this.isEnabled())return;this.logger?.debug("telemetry.metric",{telemetrySink:this.name,instrument:"histogram",name:f,value:P,attributes:O,description:A,required:T===!0})}recordGauge(f,P,O,A,T){if(!T&&!this.isEnabled())return;this.logger?.debug("telemetry.metric",{telemetrySink:this.name,instrument:"gauge",name:f,value:P,attributes:O,description:A,required:T===!0})}isEnabled(){return typeof this.enabled==="function"?this.enabled():this.enabled}async flush(){}async dispose(){}}class X{adapters;metadata;distinctId;deviceId;commonProperties;constructor(f={}){if(this.adapters=[...f.adapters??[]],f.logger)this.adapters.push(new B({logger:f.logger}));this.metadata={...f.metadata??{}},this.distinctId=f.distinctId,this.deviceId=f.deviceId??Z(),this.commonProperties={...f.commonProperties??{}}}addAdapter(f){this.adapters.push(f)}setDistinctId(f){this.distinctId=f}setMetadata(f){this.metadata={...f}}updateMetadata(f){this.metadata={...this.metadata,...f}}setCommonProperties(f){this.commonProperties={...f}}updateCommonProperties(f){this.commonProperties={...this.commonProperties,...f}}isEnabled(){return this.adapters.some((f)=>f.isEnabled())}capture(f){let P=this.buildAttributes(f.properties);for(let O of this.adapters)O.emit(f.event,P)}captureRequired(f,P){let O=this.buildAttributes(P);for(let A of this.adapters)A.emitRequired(f,O)}recordCounter(f,P,O,A,T=!1){let j=this.buildAttributes(O);for(let $ of this.adapters)$.recordCounter(f,P,j,A,T)}recordHistogram(f,P,O,A,T=!1){let j=this.buildAttributes(O);for(let $ of this.adapters)$.recordHistogram(f,P,j,A,T)}recordGauge(f,P,O,A,T=!1){let j=this.buildAttributes(O);for(let $ of this.adapters)$.recordGauge(f,P,j,A,T)}async flush(){await Promise.all(this.adapters.map((f)=>f.flush()))}async dispose(){await Promise.all(this.adapters.map((f)=>f.dispose()))}buildAttributes(f){return{...this.commonProperties,...f,...this.metadata,...this.distinctId?{distinct_id:this.distinctId}:{},device_id:this.deviceId}}}class z{distinctId;metadata;commonProperties;constructor(f={}){this.distinctId=f.distinctId,this.metadata={...f.metadata??{}},this.commonProperties={...f.commonProperties??{}}}setDistinctId(f){this.distinctId=f}setMetadata(f){this.metadata={...f}}updateMetadata(f){this.metadata={...this.metadata,...f}}setCommonProperties(f){this.commonProperties={...f}}updateCommonProperties(f){this.commonProperties={...this.commonProperties,...f}}isEnabled(){return!1}capture(f){this.resolveProperties(f.properties)}captureRequired(f,P){this.resolveProperties(P)}recordCounter(){}recordHistogram(){}recordGauge(){}async flush(){}async dispose(){}resolveProperties(f){return{...this.commonProperties,...f,...this.metadata,...this.distinctId?{distinct_id:this.distinctId}:{}}}}class R{meterProvider;loggerProvider;tracerProvider;options;constructor(f={}){this.options=f;let P=Hf({[Zf]:f.serviceName??"cline",...f.serviceVersion?{[_f]:f.serviceVersion}:{}});if(this.meterProvider=this.createMeterProvider(P),this.loggerProvider=this.createLoggerProvider(P),this.tracerProvider=this.createTracerProvider(P),this.meterProvider)ff.setGlobalMeterProvider(this.meterProvider);if(this.loggerProvider)Of.setGlobalLoggerProvider(this.loggerProvider);if(this.tracerProvider)this.tracerProvider.register()}getTracer(f="cline",P){return Pf.getTracer(f,P??this.options.serviceVersion)}createAdapter(f){return new M({...f,meterProvider:this.meterProvider,loggerProvider:this.loggerProvider})}createTelemetryService(f){let P=this.createAdapter({name:f.name,enabled:this.options.enabled,metadata:f.metadata});return new X({...f,adapters:[P],distinctId:L(f.distinctId)})}async forceFlush(){await Promise.all([this.meterProvider?.forceFlush?.(),this.loggerProvider?.forceFlush?.(),this.tracerProvider?.forceFlush?.()])}async dispose(){await Promise.all([this.meterProvider?.shutdown?.(),this.loggerProvider?.shutdown?.(),this.tracerProvider?.shutdown?.()])}createMeterProvider(f){let P=Q(this.options.metricsExporter);if(P.length===0)return null;let O=Math.max(1000,this.options.metricExportIntervalMs??this.options.metricExportInterval??60000),A=Math.min(30000,Math.floor(O*0.8)),T=P.map((j)=>Ff(j,{endpoint:this.options.otlpEndpoint,headers:this.options.otlpHeaders,insecure:this.options.otlpInsecure??!1,protocol:"http/json",interval:O,timeout:A})).filter((j)=>j!==null);if(T.length===0)return null;return new Lf({resource:f,readers:T})}createTracerProvider(f){let P=Q(this.options.tracesExporter);if(P.length===0)return null;let O=this.options.otlpTracesEndpoint??this.options.otlpEndpoint,A=this.options.otlpTracesHeaders??this.options.otlpHeaders,T=[];for(let j of P){let $=Rf(j,{endpoint:O,headers:A,insecure:this.options.otlpInsecure??!1,protocol:"http/json"});if($)T.push($)}if(T.length===0)return null;return new Yf({resource:f,spanProcessors:T})}createLoggerProvider(f){let P=Q(this.options.logsExporter);if(P.length===0)return null;let O=P.map((A)=>{let T=Qf(A,{endpoint:this.options.otlpEndpoint,headers:this.options.otlpHeaders,insecure:this.options.otlpInsecure??!1,protocol:"http/json"});if(!T)return null;return new $f(T,{maxQueueSize:this.options.logMaxQueueSize??2048,maxExportBatchSize:this.options.logBatchSize??512,scheduledDelayMillis:this.options.logBatchTimeoutMs??this.options.logBatchTimeout??5000})}).filter((A)=>A!==null);if(O.length===0)return null;return new Wf({resource:f,processors:O})}}function y(f){let P=new R(f),O=P.createTelemetryService(f),A=()=>{O.captureRequired("telemetry.provider_created",{provider:"opentelemetry",enabled:f.enabled??!0,logsExporter:Array.isArray(f.logsExporter)?f.logsExporter.join(","):f.logsExporter,metricsExporter:Array.isArray(f.metricsExporter)?f.metricsExporter.join(","):f.metricsExporter,tracesExporter:Array.isArray(f.tracesExporter)?f.tracesExporter.join(","):f.tracesExporter,otlpProtocol:f.otlpProtocol,hasOtlpEndpoint:Boolean(f.otlpEndpoint),serviceName:f.serviceName,serviceVersion:f.serviceVersion})};if(!f.deferProviderCreatedEvent)A();return{provider:P,telemetry:O,emitProviderCreated:A}}function D(f){if(N())return{telemetry:new z(f)};if(f.enabled!==!0)return{telemetry:new X({...f,distinctId:L(f.distinctId)})};return y(f)}function Bf(f){let{telemetry:P,provider:O,emitProviderCreated:A}=D(f);return{telemetry:P,provider:O,flush:async()=>{let $=O;if($&&typeof $.forceFlush==="function")try{await $.forceFlush()}catch{}},dispose:async()=>{await Promise.allSettled([P.dispose(),O?.dispose()])},...f.deferProviderCreatedEvent&&A?{emitProviderCreated:A}:{}}}function Q(f){if(!f)return[];return(Array.isArray(f)?f:f.split(",")).map((O)=>O.trim()).filter((O)=>O==="console"||O==="otlp")}function Qf(f,P){if(f==="console")return new Jf;if(!P.endpoint)return null;let O=F(P.endpoint,"/v1/logs");return new Af({url:O,headers:P.headers})}function Rf(f,P){if(f==="console")return new Xf(new Vf);if(!P.endpoint)return null;let O=F(P.endpoint,"/v1/traces");return new Mf(new jf({url:O,headers:P.headers}))}function Ff(f,P){if(f==="console")return new I({exporter:new Kf,exportIntervalMillis:P.interval,exportTimeoutMillis:P.timeout});if(!P.endpoint)return null;let O=F(P.endpoint,"/v1/metrics");return new I({exporter:new Tf({url:O,headers:P.headers}),exportIntervalMillis:P.interval,exportTimeoutMillis:P.timeout})}function F(f,P){let O=new URL(f),A=O.pathname.endsWith("/")?O.pathname.slice(0,-1):O.pathname;return O.pathname=A.endsWith(P)?A:`${A}${P}`,O.toString()}export{L as resolveCoreDistinctId,Z as resolveCoreDeviceId,y as createOpenTelemetryTelemetryService,D as createConfiguredTelemetryService,Bf as createConfiguredTelemetryHandle,R as OpenTelemetryProvider,M as OpenTelemetryAdapter};
@@ -0,0 +1,19 @@
1
+ import type { ClientContext } from "@cline/shared";
2
+ import { type SessionSource as SessionSourceValue } from "../types/common";
3
+ export interface SessionHistoryOriginMetadata {
4
+ mode: string;
5
+ version?: string;
6
+ /**
7
+ * The trigger that initiated the session, when it is not a direct user
8
+ * action. E.g., the `source` label of the automation spec that started a
9
+ * scheduled run.
10
+ */
11
+ trigger?: string;
12
+ }
13
+ export declare function resolveClientSessionSource(client: ClientContext | undefined): SessionSourceValue | undefined;
14
+ export declare function readSessionHistoryOriginMetadata(metadata: Record<string, unknown> | null | undefined): SessionHistoryOriginMetadata | undefined;
15
+ export declare function withSessionHistoryOriginMetadata(metadata: Record<string, unknown> | null | undefined, origin: {
16
+ mode?: string;
17
+ version?: string;
18
+ trigger?: string;
19
+ }): Record<string, unknown>;
@@ -34,6 +34,8 @@ export interface SessionRow {
34
34
  export interface CreateRootSessionInput {
35
35
  sessionId: string;
36
36
  source: SessionSource;
37
+ mode?: string;
38
+ version?: string;
37
39
  pid: number;
38
40
  startedAt: string;
39
41
  interactive: boolean;
@@ -52,6 +54,8 @@ export interface CreateRootSessionInput {
52
54
  export interface CreateRootSessionWithArtifactsInput {
53
55
  sessionId: string;
54
56
  source: SessionSource;
57
+ mode?: string;
58
+ version?: string;
55
59
  pid: number;
56
60
  interactive: boolean;
57
61
  provider: string;
@@ -4,6 +4,7 @@ import { SessionArtifacts } from "../../services/session-artifacts";
4
4
  import type { SessionMessagesArtifactUploader, SessionPersistenceAdapter } from "../../types/session";
5
5
  import { type SessionCompactionState } from "../models/session-compaction";
6
6
  import { type SessionManifest } from "../models/session-manifest";
7
+ import type { SessionRow } from "../models/session-row";
7
8
  export declare class SessionManifestStore {
8
9
  private readonly adapter;
9
10
  private readonly messagesArtifactUploader?;
@@ -11,7 +12,7 @@ export declare class SessionManifestStore {
11
12
  readonly artifacts: SessionArtifacts;
12
13
  constructor(adapter: SessionPersistenceAdapter, messagesArtifactUploader?: SessionMessagesArtifactUploader | undefined, logger?: BasicLogger | undefined);
13
14
  ensureSessionsDir(): string;
14
- initializeMessagesFile(sessionId: string, path: string, startedAt: string): void;
15
+ initializeMessagesFile(row: SessionRow, path: string, startedAt: string): void;
15
16
  writeSessionManifest(manifestPath: string, manifest: SessionManifest): void;
16
17
  readSessionManifest(sessionId: string): SessionManifest | undefined;
17
18
  /**
@@ -30,7 +31,14 @@ export declare class SessionManifestStore {
30
31
  path: string;
31
32
  manifest?: SessionManifest;
32
33
  };
33
- resolveArtifactPath(sessionId: string, kind: "messagesPath", fallback: (id: string) => string): Promise<string>;
34
+ /**
35
+ * Resolve the session row backing a message write, re-adopting it from the
36
+ * on-disk manifest when the DB row is missing (session artifacts restored
37
+ * or copied while the session DB was rebuilt). Sessions with neither a row
38
+ * nor a manifest throw so message writes cannot silently recreate
39
+ * orphaned session files.
40
+ */
41
+ private resolveSessionRow;
34
42
  persistSessionMessages(sessionId: string, messages: LlmsProviders.Message[], systemPrompt?: string): Promise<void>;
35
43
  private resolveCompactionPath;
36
44
  private updateCompactionPath;
@@ -40,7 +40,7 @@ export interface CoreRuntimeFeatures {
40
40
  disableMcpSettingsTools?: boolean;
41
41
  yolo?: boolean;
42
42
  }
43
- export type CoreCompactionMode = "auto" | "manual";
43
+ export type CoreCompactionMode = "auto" | "manual" | "overflow_recovery";
44
44
  export interface CoreCompactionBudget {
45
45
  request: {
46
46
  /** Estimated tokens for the full provider request. */
@@ -78,6 +78,12 @@ export interface CoreCompactionContext {
78
78
  };
79
79
  mode: CoreCompactionMode;
80
80
  budget: CoreCompactionBudget;
81
+ /**
82
+ * Aborted when the turn is cancelled. Custom `compact` implementations
83
+ * that call models or external services should observe it so a cancelled
84
+ * or recovering turn is not blocked on a stalled compaction.
85
+ */
86
+ abortSignal?: AbortSignal;
81
87
  }
82
88
  export type CoreCompactionBudgetPolicyIntent = "agentic_summary" | "basic_compaction_projection" | "normal_provider_request";
83
89
  export type CoreCompactionLiveTailHandling = "included_verbatim" | "included_degraded" | "summarized_as_context" | "omitted_with_warning" | "preserved_out_of_band";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cline/core",
3
3
  "description": "Cline Core SDK for Node Runtime",
4
- "version": "0.0.69",
4
+ "version": "0.0.70",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/cline/cline",
@@ -49,9 +49,9 @@
49
49
  "test:watch": "vitest --config vitest.config.ts"
50
50
  },
51
51
  "dependencies": {
52
- "@cline/agents": "0.0.69",
53
- "@cline/shared": "0.0.69",
54
- "@cline/llms": "0.0.69",
52
+ "@cline/agents": "0.0.70",
53
+ "@cline/shared": "0.0.70",
54
+ "@cline/llms": "0.0.70",
55
55
  "@modelcontextprotocol/sdk": "^1.29.0",
56
56
  "@opentelemetry/api": "^1.9.0",
57
57
  "@opentelemetry/api-logs": "^0.214.0",