@cerebriline/core 4.100.246 → 4.100.247

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 (116) hide show
  1. package/assets/prompt-templates/claude.md +2 -0
  2. package/assets/prompt-templates/deepseek.md +1 -0
  3. package/assets/prompt-templates/default.md +2 -1
  4. package/assets/prompt-templates/kimi-k3.md +1 -0
  5. package/assets/prompt-templates/kimi.md +1 -0
  6. package/assets/prompt-templates/minimax.md +2 -0
  7. package/assets/prompt-templates/nemotron.md +1 -0
  8. package/assets/skills/browser-automation/SKILL.md +113 -0
  9. package/dist/ClineCore.d.ts +9 -0
  10. package/dist/account/index.d.ts +1 -0
  11. package/dist/account/telemetry.d.ts +22 -0
  12. package/dist/cloud/api.d.ts +122 -0
  13. package/dist/cloud/controller.d.ts +172 -0
  14. package/dist/cloud/index.d.ts +9 -0
  15. package/dist/cloud/index.js +21 -0
  16. package/dist/cloud/models.d.ts +9 -0
  17. package/dist/cloud/repositories.d.ts +21 -0
  18. package/dist/cloud/snapshots.d.ts +22 -0
  19. package/dist/cloud/state.d.ts +13 -0
  20. package/dist/cloud/types.d.ts +84 -0
  21. package/dist/cron/events/cron-event-ingress.d.ts +4 -2
  22. package/dist/cron/runner/cron-runner.d.ts +5 -2
  23. package/dist/cron/service/cron-service.d.ts +2 -1
  24. package/dist/cron/service/schedule-service.d.ts +2 -1
  25. package/dist/cron/store/sqlite-cron-store.d.ts +7 -1
  26. package/dist/extensions/composio/composio-meta-tools.d.ts +39 -0
  27. package/dist/extensions/composio/composio-tools-extension.d.ts +13 -0
  28. package/dist/extensions/context/agentic-compaction.d.ts +1 -1
  29. package/dist/extensions/context/cap-thoughts.d.ts +39 -0
  30. package/dist/extensions/context/compaction-shared.d.ts +76 -1
  31. package/dist/extensions/context/compaction.d.ts +75 -3
  32. package/dist/extensions/mcp/client.d.ts +1 -1
  33. package/dist/extensions/tools/definitions.d.ts +5 -5
  34. package/dist/extensions/tools/executors/bash.d.ts +26 -0
  35. package/dist/extensions/tools/executors/index.d.ts +1 -1
  36. package/dist/extensions/tools/index.d.ts +1 -1
  37. package/dist/extensions/tools/task-progress.d.ts +37 -0
  38. package/dist/extensions/tools/team/index.d.ts +1 -0
  39. package/dist/extensions/tools/team/multi-agent.d.ts +48 -0
  40. package/dist/extensions/tools/team/persistence-policy.d.ts +56 -0
  41. package/dist/extensions/tools/team/runtime.d.ts +1 -1
  42. package/dist/extensions/tools/team/sanitize-team-name.d.ts +5 -0
  43. package/dist/extensions/tools/team/team-tools.d.ts +1 -1
  44. package/dist/hooks/checkpoint-hooks.d.ts +23 -1
  45. package/dist/hooks/hook-file-hooks.d.ts +27 -0
  46. package/dist/hooks/subprocess-runner.d.ts +23 -0
  47. package/dist/hooks/subprocess.d.ts +10 -0
  48. package/dist/hub/client/index.d.ts +29 -3
  49. package/dist/hub/client/session-client.d.ts +0 -3
  50. package/dist/hub/daemon/bind-diagnostics.d.ts +16 -0
  51. package/dist/hub/daemon/entry.js +689 -640
  52. package/dist/hub/daemon/index.d.ts +17 -8
  53. package/dist/hub/discovery/index.d.ts +1 -0
  54. package/dist/hub/index.js +675 -627
  55. package/dist/hub/runtime-host/hub-runtime-host.d.ts +4 -2
  56. package/dist/hub/server/handlers/session-handlers.d.ts +6 -1
  57. package/dist/index.d.ts +21 -11
  58. package/dist/index.js +1032 -964
  59. package/dist/remote/remote-environments.d.ts +155 -0
  60. package/dist/remote/remote-helper-entry.d.ts +1 -0
  61. package/dist/remote/remote-helper-entry.js +5 -0
  62. package/dist/remote/remote-helper.d.ts +29 -0
  63. package/dist/remote/remote-helper.js +4 -0
  64. package/dist/remote/shell-path.d.ts +88 -0
  65. package/dist/runtime/host/local-runtime-host.d.ts +2 -2
  66. package/dist/runtime/host/runtime-host.d.ts +13 -1
  67. package/dist/runtime/orchestration/oauth-refresh-lock.d.ts +6 -0
  68. package/dist/runtime/orchestration/session-runtime-orchestrator.d.ts +7 -0
  69. package/dist/runtime/orchestration/team-persistence-writer.d.ts +65 -0
  70. package/dist/runtime/safety/rules.d.ts +11 -0
  71. package/dist/runtime/turn-queue/pending-prompt-service.d.ts +1 -0
  72. package/dist/services/agent-events.d.ts +1 -0
  73. package/dist/services/cloud-handoff/git-preflight.d.ts +24 -0
  74. package/dist/services/cloud-handoff/index.d.ts +4 -0
  75. package/dist/services/cloud-handoff/metadata.d.ts +7 -0
  76. package/dist/services/cloud-handoff/transcript.d.ts +5 -0
  77. package/dist/services/cloud-handoff/types.d.ts +35 -0
  78. package/dist/services/feature-flags/FeatureFlagsService.d.ts +2 -0
  79. package/dist/services/feature-flags/cline-account-feature-flags.d.ts +5 -0
  80. package/dist/services/llms/cline-recommended-models.d.ts +1 -0
  81. package/dist/services/llms/handler-factory.d.ts +12 -0
  82. package/dist/services/llms/provider-defaults.d.ts +1 -1
  83. package/dist/services/llms/provider-settings.d.ts +19 -17
  84. package/dist/services/local-runtime-bootstrap.d.ts +7 -0
  85. package/dist/services/mcp-install.d.ts +9 -0
  86. package/dist/services/plugin-commands.d.ts +28 -0
  87. package/dist/services/providers/local-provider-registry.d.ts +8 -3
  88. package/dist/services/providers/local-provider-service.d.ts +20 -10
  89. package/dist/services/providers/model-source.d.ts +6 -1
  90. package/dist/services/providers/provider-config-fields.d.ts +11 -0
  91. package/dist/services/session-import/claude-code.d.ts +1 -1
  92. package/dist/services/session-import/paths.d.ts +9 -0
  93. package/dist/services/storage/file-team-store.d.ts +10 -4
  94. package/dist/services/storage/sqlite-team-store.d.ts +48 -5
  95. package/dist/services/storage/team-store.d.ts +1 -0
  96. package/dist/services/telemetry/core-events.d.ts +97 -5
  97. package/dist/services/telemetry/index.d.ts +1 -0
  98. package/dist/services/telemetry/index.js +1 -1
  99. package/dist/services/telemetry/scoped-telemetry.d.ts +31 -0
  100. package/dist/services/workspace/workspace-manifest.d.ts +34 -0
  101. package/dist/services/workspace/workspace-telemetry.d.ts +5 -0
  102. package/dist/session/fork-metadata.d.ts +7 -0
  103. package/dist/session/models/session-compaction.d.ts +8 -1
  104. package/dist/session/services/message-builder.d.ts +8 -1
  105. package/dist/session/services/persistence-service.d.ts +4 -1
  106. package/dist/session/services/tool-result-cache.d.ts +30 -0
  107. package/dist/session/session-versioning-service.d.ts +8 -0
  108. package/dist/session/stores/session-manifest-store.d.ts +2 -4
  109. package/dist/session/team/team-session-coordinator.d.ts +3 -1
  110. package/dist/tasks/task-tool.d.ts +2 -2
  111. package/dist/types/provider-settings.d.ts +11 -0
  112. package/dist/types/session.d.ts +2 -0
  113. package/dist/types/storage.d.ts +22 -1
  114. package/package.json +16 -4
  115. package/dist/cron/runner/resource-limiter.d.ts +0 -8
  116. package/dist/services/storage/team-events-retention.d.ts +0 -25
@@ -1,8 +1,7 @@
1
1
  import type { TeamRuntimeState, TeamTeammateSpec } from "@cerebriline/shared";
2
2
  import type { TeamEvent } from "../../extensions/tools/team";
3
- import type { TeamStore } from "../../types/storage";
4
- import { type TeamEventsRetention } from "./team-events-retention";
5
- export interface FileTeamStoreOptions extends TeamEventsRetention {
3
+ import type { TeamPersistenceBatch, TeamStore } from "../../types/storage";
4
+ export interface FileTeamStoreOptions {
6
5
  teamDir?: string;
7
6
  }
8
7
  export interface TeamRuntimeLoadResult {
@@ -12,7 +11,6 @@ export interface TeamRuntimeLoadResult {
12
11
  }
13
12
  export declare class FileTeamStore implements TeamStore {
14
13
  private readonly teamDirPath;
15
- private readonly eventsPrune;
16
14
  constructor(options?: FileTeamStoreOptions);
17
15
  /** Nothing is held open between calls; present so both stores close alike. */
18
16
  close(): void;
@@ -22,6 +20,14 @@ export declare class FileTeamStore implements TeamStore {
22
20
  readHistory(teamName: string, limit?: number): unknown[];
23
21
  loadRuntime(teamName: string): TeamRuntimeLoadResult;
24
22
  handleTeamEvent(teamName: string, event: TeamEvent): void;
23
+ /**
24
+ * The file store cannot apply deltas, so it rewrites `state.json` once per
25
+ * batch. Batching plus compacted run results keep that file small.
26
+ */
27
+ persistBatch(teamName: string, batch: TeamPersistenceBatch): void;
28
+ private appendHistory;
29
+ /** Keep the newest `retentionPerTeam` lines once the file grows too big. */
30
+ private compactHistoryIfNeeded;
25
31
  persistRuntime(teamName: string, state: TeamRuntimeState, teammates: TeamTeammateSpec[]): void;
26
32
  markInProgressRunsInterrupted(teamName: string, reason: string): string[];
27
33
  private ensureTeamDir;
@@ -1,8 +1,7 @@
1
1
  import { type TeamRuntimeState, type TeamTeammateSpec } from "@cerebriline/shared";
2
2
  import type { TeamEvent } from "../../extensions/tools/team";
3
- import type { TeamStore } from "../../types/storage";
4
- import { type TeamEventsRetention } from "./team-events-retention";
5
- export interface SqliteTeamStoreOptions extends TeamEventsRetention {
3
+ import type { TeamPersistenceBatch, TeamStore } from "../../types/storage";
4
+ export interface SqliteTeamStoreOptions {
6
5
  teamDir?: string;
7
6
  }
8
7
  export interface TeamRuntimeLoadResult {
@@ -10,11 +9,20 @@ export interface TeamRuntimeLoadResult {
10
9
  teammates: TeamTeammateSpec[];
11
10
  interruptedRunIds: string[];
12
11
  }
12
+ /** Durable event rows kept per team (history tool reads newest-first). */
13
+ export declare const TEAM_EVENT_RETENTION_PER_TEAM = 2000;
14
+ /** Event rows older than this are pruned regardless of count. */
15
+ export declare const TEAM_EVENT_RETENTION_MS: number;
16
+ export interface SqliteTeamStoreTuning {
17
+ eventRetentionPerTeam?: number;
18
+ eventRetentionMs?: number;
19
+ }
13
20
  export declare class SqliteTeamStore implements TeamStore {
14
21
  private readonly teamDirPath;
15
22
  private db;
16
- private readonly eventsPrune;
17
- constructor(options?: SqliteTeamStoreOptions);
23
+ private readonly retentionPerTeam;
24
+ private readonly retentionMs;
25
+ constructor(options?: SqliteTeamStoreOptions & SqliteTeamStoreTuning);
18
26
  init(): void;
19
27
  /**
20
28
  * Releases the database handle. The next call reopens it, so a store that
@@ -26,17 +34,52 @@ export declare class SqliteTeamStore implements TeamStore {
26
34
  private dbPath;
27
35
  private getRawDb;
28
36
  private ensureSchema;
37
+ /**
38
+ * Moves any non-empty `state_json` into entity rows, then clears it.
39
+ * v2+ builds only ever write `''`, so a non-empty value was written by an
40
+ * older build (e.g. after an image rollback). Runs on every open, not just
41
+ * the v2 migration, so those writes are recovered after re-upgrading.
42
+ * Caller owns the transaction.
43
+ */
44
+ private importLegacySnapshots;
45
+ /**
46
+ * v2 migration (one-time, transactional):
47
+ * - adds `data_json` to entity tables and new members/mailbox/mission-log
48
+ * tables, so state is rebuilt from rows instead of `state_json`;
49
+ * - moves each existing snapshot into rows, compacting run results;
50
+ * - deletes telemetry events and strips transcripts from retained ones;
51
+ * - clears `state_json` (the column stays for downgrade-safe schema).
52
+ * Run `vacuum()` afterwards to give the space back to the OS.
53
+ */
54
+ private migrateToV2;
29
55
  private run;
30
56
  private queryOne;
31
57
  private queryAll;
32
58
  /** Runs `work` in a single SQLite transaction (rollback on any error). */
33
59
  private withTransaction;
34
60
  listTeamNames(): string[];
61
+ /** Rebuild state from per-entity rows. Cost is O(live entities). */
35
62
  readState(teamName: string): TeamRuntimeState | undefined;
36
63
  readHistory(teamName: string, limit?: number): unknown[];
37
64
  loadRuntime(teamName: string): TeamRuntimeLoadResult;
38
65
  appendTeamEvent(teamName: string, eventType: string, payload: unknown, correlationId?: string): void;
66
+ /**
67
+ * Incremental write: appends events and upserts only changed entities in
68
+ * one transaction. Cost is O(changes in batch), independent of history.
69
+ */
70
+ persistBatch(teamName: string, batch: TeamPersistenceBatch): void;
71
+ /** Full rewrite, expressed as a reset delta (no `state_json` blob). */
39
72
  persistRuntime(teamName: string, state: TeamRuntimeState, teammates: TeamTeammateSpec[]): void;
73
+ private writeTeammates;
74
+ private writeDelta;
75
+ /** Cap `team_events` per team by count and by age. */
76
+ private pruneTeamEvents;
77
+ /**
78
+ * Return free pages to the OS after the v2 migration or heavy pruning.
79
+ * VACUUM rewrites the whole file, so it is explicit, not automatic.
80
+ */
81
+ vacuum(): void;
40
82
  markInProgressRunsInterrupted(teamName: string, reason: string): string[];
83
+ /** Legacy single-event path: telemetry is dropped, payloads compacted. */
41
84
  handleTeamEvent(teamName: string, event: TeamEvent): void;
42
85
  }
@@ -10,6 +10,7 @@ export declare function createLocalTeamStore(options?: SqliteTeamStoreOptions):
10
10
  readHistory(teamName: string, limit?: number): unknown[];
11
11
  loadRuntime(teamName: string): ReturnType<FileTeamStore["loadRuntime"]>;
12
12
  handleTeamEvent: FileTeamStore["handleTeamEvent"];
13
+ persistBatch: FileTeamStore["persistBatch"];
13
14
  persistRuntime: FileTeamStore["persistRuntime"];
14
15
  markInProgressRunsInterrupted: FileTeamStore["markInProgressRunsInterrupted"];
15
16
  close(): void;
@@ -14,12 +14,17 @@ export interface TelemetryAgentIdentityProperties {
14
14
  teamAgentId?: string;
15
15
  }
16
16
  export declare const CORE_TELEMETRY_EVENTS: {
17
+ readonly SCHEDULE: {
18
+ readonly RUN_STARTED: "schedule.run_started";
19
+ readonly RUN_FINISHED: "schedule.run_finished";
20
+ };
17
21
  readonly CLIENT: {
18
22
  readonly EXTENSION_ACTIVATED: "user.extension_activated";
19
23
  };
20
24
  readonly SESSION: {
21
25
  readonly STARTED: "session.started";
22
26
  readonly ENDED: "session.ended";
27
+ readonly ERROR_RECORDED: "session.error_recorded";
23
28
  };
24
29
  readonly AGENT: {
25
30
  readonly UNEXPECTED_REASONING_TOKENS: "agent.reasoning.unexpected_tokens";
@@ -38,6 +43,7 @@ export declare const CORE_TELEMETRY_EVENTS: {
38
43
  readonly CREATED: "task.created";
39
44
  readonly RESTARTED: "task.restarted";
40
45
  readonly COMPLETED: "task.completed";
46
+ readonly GIT_SNAPSHOT: "task.git_snapshot";
41
47
  readonly CONVERSATION_TURN: "task.conversation_turn";
42
48
  readonly TOKEN_USAGE: "task.tokens";
43
49
  readonly MODE_SWITCH: "task.mode";
@@ -50,6 +56,7 @@ export declare const CORE_TELEMETRY_EVENTS: {
50
56
  readonly PROVIDER_STREAM_STARTED: "task.provider_stream_started";
51
57
  readonly FIRST_CHUNK_RECEIVED: "task.first_chunk_received";
52
58
  readonly PROVIDER_STREAM_FAILED: "task.provider_stream_failed";
59
+ readonly MAX_TOKENS_RECOVERY: "task.max_tokens_recovery";
53
60
  readonly CANCELLED: "task.cancelled";
54
61
  readonly MENTION_USED: "task.mention_used";
55
62
  readonly MENTION_FAILED: "task.mention_failed";
@@ -64,6 +71,7 @@ export declare const CORE_TELEMETRY_EVENTS: {
64
71
  };
65
72
  readonly HOOKS: {
66
73
  readonly DISCOVERY_COMPLETED: "hooks.discovery_completed";
74
+ readonly DETACHED_RUNTIME: "hooks.detached_runtime";
67
75
  };
68
76
  readonly WORKSPACE: {
69
77
  readonly INITIALIZED: "workspace.initialized";
@@ -96,6 +104,46 @@ export interface RunCommandsTimeoutTelemetryProperties {
96
104
  tool_call_id?: string;
97
105
  }
98
106
  export { captureAgentUnexpectedReasoningTokens, captureTaskLifecycleEvent, type CaptureAgentUnexpectedReasoningTokensInput, type CaptureTaskLifecycleEventInput, };
107
+ export interface GitSnapshotProperties {
108
+ schema_version: 1;
109
+ /** Actual Core session ID; ulid duplicates it for existing export consumers. */
110
+ sessionId: string;
111
+ ulid: string;
112
+ providerId: string;
113
+ workspace_id: string;
114
+ /** VS Code workspace-folder count at observation start, not Git repo count; 0 with no folders, even outside Git. */
115
+ workspace_root_count: number;
116
+ observation_window_id: string;
117
+ observation_sequence: number;
118
+ /** ISO observation-start time, after the model response. Git reads are not atomic. */
119
+ observed_at: string;
120
+ /** Background observation triggered by this response; tools may execute during the read. */
121
+ boundary: "model_call";
122
+ runId?: string;
123
+ iteration?: number;
124
+ agentId?: string;
125
+ /** Surfaced response's backend ID, when available; never synthesized or inherited from an earlier request. */
126
+ request_id?: string;
127
+ request_id_status: "present" | "missing";
128
+ git: {
129
+ /** partial: status hit its timeout/output cap but separate reads recovered HEAD and/or branch. */
130
+ state: "ok" | "unborn" | "non_git" | "unavailable" | "partial";
131
+ head_sha?: string;
132
+ branch?: string;
133
+ /** Any staged/unstaged/untracked changes. All four flags are absent for partial/non_git/unavailable, not false. */
134
+ dirty?: boolean;
135
+ /** Index changes, including unmerged entries; does not imply commit readiness. */
136
+ staged?: boolean;
137
+ /** Worktree changes, including unmerged entries. */
138
+ unstaged?: boolean;
139
+ /** Non-ignored untracked files. */
140
+ untracked?: boolean;
141
+ remote_url?: string;
142
+ remote_state?: "ok" | "none" | "unsupported" | "unavailable";
143
+ };
144
+ }
145
+ /** Ordinary telemetry: use a consent-aware service, never captureRequired. */
146
+ export declare function captureGitSnapshot(telemetry: ITelemetryService | undefined, properties: GitSnapshotProperties): void;
99
147
  export interface WorkspaceInitializedProperties {
100
148
  root_count: number;
101
149
  vcs_types: ReadonlyArray<string>;
@@ -181,15 +229,23 @@ export declare function identifyAccount(telemetry: ITelemetryService | undefined
181
229
  organizationName?: string;
182
230
  memberId?: string;
183
231
  }): void;
232
+ /**
233
+ * Restore anonymous process identity after an account signs out.
234
+ *
235
+ * Account properties are explicitly set to undefined so they replace values
236
+ * previously merged into a long-lived telemetry service. Implementations
237
+ * remove undefined attributes before export.
238
+ */
239
+ export declare function clearAccountTelemetryIdentity(telemetry: ITelemetryService | undefined, anonymousDistinctId?: string): void;
184
240
  export declare function captureTaskCreated(telemetry: ITelemetryService | undefined, properties: {
185
241
  ulid: string;
186
- apiProvider?: string;
187
- openAiCompatibleDomain?: string;
242
+ provider?: string;
243
+ model?: string;
188
244
  } & Partial<TelemetryAgentIdentityProperties>): void;
189
245
  export declare function captureTaskRestarted(telemetry: ITelemetryService | undefined, properties: {
190
246
  ulid: string;
191
- apiProvider?: string;
192
- openAiCompatibleDomain?: string;
247
+ provider?: string;
248
+ model?: string;
193
249
  } & Partial<TelemetryAgentIdentityProperties>): void;
194
250
  /**
195
251
  * Distinguishes the trigger that produced a `task.completed` telemetry event.
@@ -206,7 +262,7 @@ export type TaskCompletedSource = "submit_and_exit" | "shutdown";
206
262
  export declare function captureTaskCompleted(telemetry: ITelemetryService | undefined, properties: {
207
263
  ulid: string;
208
264
  provider?: string;
209
- modelId?: string;
265
+ model?: string;
210
266
  mode?: string;
211
267
  durationMs?: number;
212
268
  source?: TaskCompletedSource;
@@ -222,11 +278,14 @@ export declare function captureTokenUsage(telemetry: ITelemetryService | undefin
222
278
  ulid: string;
223
279
  /** Uncached input tokens only — disjoint from the cache buckets. */
224
280
  tokensIn: number;
281
+ /** Non-reasoning output tokens only — reasoningTokenCount is disjoint from this. */
225
282
  tokensOut: number;
226
283
  cacheWriteTokens?: number;
227
284
  cacheReadTokens?: number;
228
285
  /** This request's cost delta, not a running total. */
229
286
  totalCost?: number;
287
+ /** Reasoning/thinking tokens for this request, reported separately since they're no longer folded into tokensOut. */
288
+ reasoningTokenCount?: number;
230
289
  provider?: string;
231
290
  model: string;
232
291
  } & Partial<TelemetryAgentIdentityProperties>): void;
@@ -316,6 +375,20 @@ export declare function captureSubagentExecution(telemetry: ITelemetryService |
316
375
  errorMessage?: string;
317
376
  type?: "agent" | "team";
318
377
  } & Partial<TelemetryAgentIdentityProperties>): void;
378
+ /**
379
+ * Records how long a fire-and-forget hook ran. Detached hooks are never
380
+ * awaited, so their runtime is otherwise invisible — this is the evidence for
381
+ * whether any of them could safely be made blocking. `exited: false` marks a
382
+ * censored observation: the hook was still running when the observation
383
+ * window closed, so treat `durationMs` as a lower bound and count these
384
+ * separately rather than averaging them in.
385
+ */
386
+ export declare function captureDetachedHookRuntime(telemetry: ITelemetryService | undefined, event: {
387
+ hookName: string;
388
+ durationMs: number;
389
+ exitCode: number | null;
390
+ exited: boolean;
391
+ }): void;
319
392
  export declare function captureHookDiscovery(telemetry: ITelemetryService | undefined, hookName: string, globalCount: number, workspaceCount: number): void;
320
393
  /**
321
394
  * Identifies which compaction implementation produced a
@@ -394,3 +467,22 @@ export interface CaptureCompactionBudgetEmergencyProperties {
394
467
  modelId?: string;
395
468
  }
396
469
  export declare function captureCompactionBudgetEmergency(telemetry: ITelemetryService | undefined, properties: CaptureCompactionBudgetEmergencyProperties & Partial<TelemetryAgentIdentityProperties>): void;
470
+ /** A terminal failure was recorded as a display-only transcript entry. */
471
+ export declare function captureSessionErrorRecorded(telemetry: ITelemetryService | undefined, details: {
472
+ sessionId?: string;
473
+ provider: string;
474
+ model: string;
475
+ source: "result" | "thrown";
476
+ }): void;
477
+ /** Bounded scheduler diagnostics; never include prompts, paths, or raw errors. */
478
+ export declare function captureScheduleRun(telemetry: ITelemetryService | undefined, input: {
479
+ triggerKind: "one_off" | "schedule" | "event" | "manual" | "retry";
480
+ attemptCount: number;
481
+ startDelayMs: number;
482
+ } & ({
483
+ phase: "started";
484
+ } | {
485
+ phase: "finished";
486
+ outcome: "success" | "failed" | "timeout" | "superseded" | "cancelled";
487
+ durationMs: number;
488
+ })): void;
@@ -2,3 +2,4 @@ export { resolveCoreDeviceId, resolveCoreDistinctId } from "./distinct-id";
2
2
  export type { ITelemetryAdapter, TelemetryArray, TelemetryMetadata, TelemetryObject, TelemetryPrimitive, TelemetryProperties, TelemetryValue, } from "./ITelemetryAdapter";
3
3
  export { OpenTelemetryAdapter, type OpenTelemetryAdapterOptions, } from "./OpenTelemetryAdapter";
4
4
  export { type ConfiguredTelemetryHandle, type CreateOpenTelemetryTelemetryServiceOptions, createConfiguredTelemetryHandle, createConfiguredTelemetryService, createOpenTelemetryTelemetryService, OpenTelemetryProvider, type OpenTelemetryProviderOptions, } from "./OpenTelemetryProvider";
5
+ export { type ClientTelemetryContext, createClientScopedTelemetryService, createScopedTelemetryService, resolveClientTelemetryProperties, } from "./scoped-telemetry";
@@ -1 +1 @@
1
- import{existsSync as N,mkdirSync as G,readFileSync as v,writeFileSync as u}from"node:fs";import{resolve as b}from"node:path";import{resolveSessionDataDir as S}from"@cerebriline/shared/storage";import{nanoid as g}from"nanoid";import*as c from"node-machine-id";var m="machine-id",C,w=!1;function B(){if(!w)C=h(),w=!0;return C??q()}function X(f){let P=f?.trim();if(P)return P;let A=h();if(A)return A;return q()}function d(){let f=c;return f.machineIdSync??f.default?.machineIdSync}function h(){try{let f=d();if(!f)return;return f().trim()||void 0}catch{return}}function q(){let f=S(),P=b(f,m);try{if(N(P)){let O=v(P,"utf8").trim();if(O.length>0)return O}}catch{}let A=`cl-${g()}`;try{G(f,{recursive:!0}),u(P,A,"utf8")}catch{}return A}class Y{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,A,O,j=!1){if(!this.meter||!j&&!this.isEnabled())return;let H=this.counters.get(f);if(!H)H=this.meter.createCounter(f,O?{description:O}:void 0),this.counters.set(f,H);H.add(P,this.flattenProperties(this.buildAttributes(A)))}recordHistogram(f,P,A,O,j=!1){if(!this.meter||!j&&!this.isEnabled())return;let H=this.histograms.get(f);if(!H)H=this.meter.createHistogram(f,O?{description:O}:void 0),this.histograms.set(f,H);H.record(P,this.flattenProperties(this.buildAttributes(A)))}recordGauge(f,P,A,O,j=!1){if(!this.meter||!j&&!this.isEnabled())return;let H=this.buildAttributes(A),J=JSON.stringify(H),K=this.gaugeValues.get(f);if(P===null){if(K){if(K.delete(J),K.size===0)this.gaugeValues.delete(f),this.gauges.delete(f)}return}let T=K;if(!T)T=new Map,this.gaugeValues.set(f,T);if(!this.gauges.has(f)){let W=this.meter.createObservableGauge(f,O?{description:O}:void 0);W.addCallback((R)=>{for(let M of this.snapshotGaugeSeries(f))R.observe(M.value,this.flattenProperties(M.attributes))}),this.gauges.set(f,W)}T.set(J,{value:P,attributes:H})}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,A){if(!this.logger)return;let O=this.flattenProperties(this.buildAttributes(P,A));this.logger.emit({severityText:"INFO",body:f,attributes:O})}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(),(A)=>({value:A.value,attributes:A.attributes?{...A.attributes}:void 0}))}flattenProperties(f,P="",A=new WeakSet,O=0){if(!f)return{};let j={},H=100,J=10;for(let[K,T]of Object.entries(f)){if(K==="__proto__"||K==="constructor"||K==="prototype")continue;let W=P?`${P}.${K}`:K;if(T===null||T===void 0){j[W]=String(T);continue}if(Array.isArray(T)){let R=T.length>H?T.slice(0,H):T;try{j[W]=JSON.stringify(R)}catch{j[W]="[UnserializableArray]"}if(T.length>H)j[`${W}_truncated`]=!0,j[`${W}_original_length`]=T.length;continue}if(typeof T==="object"){if(T instanceof Date){j[W]=T.toISOString();continue}if(T instanceof Error){j[W]=T.message;continue}if(A.has(T)){j[W]="[Circular]";continue}if(O>=J){j[W]="[MaxDepthExceeded]";continue}A.add(T),Object.assign(j,this.flattenProperties(T,W,A,O+1));continue}if(r(T)){j[W]=T;continue}try{j[W]=JSON.stringify(T)}catch{j[W]=String(T)}}return j}}function r(f){return typeof f==="string"||typeof f==="number"||typeof f==="boolean"}import{metrics as Of,trace as jf}from"@opentelemetry/api";import{logs as Hf}from"@opentelemetry/api-logs";import{OTLPLogExporter as Tf}from"@opentelemetry/exporter-logs-otlp-http";import{OTLPMetricExporter as $f}from"@opentelemetry/exporter-metrics-otlp-http";import{OTLPTraceExporter as Jf}from"@opentelemetry/exporter-trace-otlp-http";import{resourceFromAttributes as Wf}from"@opentelemetry/resources";import{BatchLogRecordProcessor as Kf,ConsoleLogRecordExporter as Xf,LoggerProvider as Yf}from"@opentelemetry/sdk-logs";import{ConsoleMetricExporter as Zf,MeterProvider as Qf,PeriodicExportingMetricReader as y}from"@opentelemetry/sdk-metrics";import{BatchSpanProcessor as Rf,ConsoleSpanExporter as Bf,SimpleSpanProcessor as Ff}from"@opentelemetry/sdk-trace-base";import{NodeTracerProvider as Vf}from"@opentelemetry/sdk-trace-node";import{ATTR_SERVICE_NAME as Uf,ATTR_SERVICE_VERSION as _f}from"@opentelemetry/semantic-conventions";import{mkdirSync as rf,readFileSync as l,statSync as n,writeFileSync as lf}from"node:fs";import{CONFIGURABLE_MODEL_TOOL_NAMES as p}from"@cerebriline/shared";import{resolveGlobalSettingsPath as a}from"@cerebriline/shared/storage";import{z as $}from"zod";import{AGENT_UNEXPECTED_REASONING_TOKENS_EVENT as zf,captureAgentUnexpectedReasoningTokens as xf,captureTaskLifecycleEvent as Nf,SDK_ERROR_TELEMETRY_EVENT as Gf,TASK_CANCELLED_EVENT as vf,TASK_FIRST_CHUNK_RECEIVED_EVENT as uf,TASK_PROVIDER_REQUEST_STARTED_EVENT as bf,TASK_PROVIDER_STREAM_FAILED_EVENT as Sf,TASK_PROVIDER_STREAM_STARTED_EVENT as gf}from"@cerebriline/shared";var F=$.preprocess((f)=>Array.isArray(f)?f.filter((P)=>typeof P==="string").map((P)=>P.trim()).filter(Boolean):void 0,$.array($.string()).optional()).transform((f)=>{if(!f)return;let P=[...new Set(f)].sort((A,O)=>A.localeCompare(O));return P.length>0?P:void 0}),i=$.enum(["basic","agentic"]).catch("agentic"),s=$.partialRecord($.enum(p),$.object({enabled:$.boolean()}).strip()).optional(),o=$.record($.string(),$.object({enabled:$.boolean()}).strip()).optional().catch(void 0),t=$.enum(["plan","act"]),E=$.object({telemetryOptOut:$.boolean().default(!1).catch(!1),autoUpdateEnabled:$.boolean().default(!0).catch(!0),compactionStrategy:i.optional(),compactionEnabled:$.boolean().optional().catch(void 0),planActMode:t.optional().catch(void 0),toolAutoApprove:$.boolean().optional().catch(void 0),tuiTheme:$.string().optional().catch(void 0),disabledTools:F.optional(),tools:s,disabledPlugins:F.optional(),disabledAgentPlugins:F.optional(),bundledSkills:o}).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.tools&&Object.keys(f.tools).length>0)P.tools=f.tools;if(f.disabledPlugins?.length)P.disabledPlugins=f.disabledPlugins;if(f.disabledAgentPlugins?.length)P.disabledAgentPlugins=f.disabledAgentPlugins;if(f.bundledSkills&&Object.keys(f.bundledSkills).length>0)P.bundledSkills=f.bundledSkills;return P});function Z(){return E.parse({})}var V;function e(f){if(f.disabledTools)Object.freeze(f.disabledTools);if(f.tools){for(let P of Object.values(f.tools))Object.freeze(P);Object.freeze(f.tools)}if(f.disabledPlugins)Object.freeze(f.disabledPlugins);if(f.disabledAgentPlugins)Object.freeze(f.disabledAgentPlugins);return Object.freeze(f)}function ff(f){let P;try{P=l(f,"utf8")}catch{return Z()}try{let A=E.safeParse(JSON.parse(P));return A.success?A.data:Z()}catch{return Z()}}function Pf(){let f=a(),P=n(f,{throwIfNoEntry:!1}),A=P?.mtimeMs??0,O=P?.size??0,j=V;if(j&&j.path===f&&j.mtimeMs===A&&j.size===O)return j;let H=e(P?ff(f):Z());return V={path:f,mtimeMs:A,size:O,value:H},V}function Af(){return Pf().value}function I(){return Af().telemetryOptOut}class U{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,A,O,j){if(!j&&!this.isEnabled())return;this.logger?.debug("telemetry.metric",{telemetrySink:this.name,instrument:"counter",name:f,value:P,attributes:A,description:O,required:j===!0})}recordHistogram(f,P,A,O,j){if(!j&&!this.isEnabled())return;this.logger?.debug("telemetry.metric",{telemetrySink:this.name,instrument:"histogram",name:f,value:P,attributes:A,description:O,required:j===!0})}recordGauge(f,P,A,O,j){if(!j&&!this.isEnabled())return;this.logger?.debug("telemetry.metric",{telemetrySink:this.name,instrument:"gauge",name:f,value:P,attributes:A,description:O,required:j===!0})}isEnabled(){return typeof this.enabled==="function"?this.enabled():this.enabled}async flush(){}async dispose(){}}class Q{adapters;metadata;distinctId;deviceId;commonProperties;constructor(f={}){if(this.adapters=[...f.adapters??[]],f.logger)this.adapters.push(new U({logger:f.logger}));this.metadata={...f.metadata??{}},this.distinctId=f.distinctId,this.deviceId=f.deviceId??B(),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 A of this.adapters)A.emit(f.event,P)}captureRequired(f,P){let A=this.buildAttributes(P);for(let O of this.adapters)O.emitRequired(f,A)}recordCounter(f,P,A,O,j=!1){let H=this.buildAttributes(A);for(let J of this.adapters)J.recordCounter(f,P,H,O,j)}recordHistogram(f,P,A,O,j=!1){let H=this.buildAttributes(A);for(let J of this.adapters)J.recordHistogram(f,P,H,O,j)}recordGauge(f,P,A,O,j=!1){let H=this.buildAttributes(A);for(let J of this.adapters)J.recordGauge(f,P,H,O,j)}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 D{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 L{meterProvider;loggerProvider;tracerProvider;options;constructor(f={}){this.options=f;let P=Wf({[Uf]: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)Of.setGlobalMeterProvider(this.meterProvider);if(this.loggerProvider)Hf.setGlobalLoggerProvider(this.loggerProvider);if(this.tracerProvider)this.tracerProvider.register()}getTracer(f="cline",P){return jf.getTracer(f,P??this.options.serviceVersion)}createAdapter(f){return new Y({...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 Q({...f,adapters:[P],distinctId:X(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=_(this.options.metricsExporter);if(P.length===0)return null;let A=Math.max(1000,this.options.metricExportIntervalMs??this.options.metricExportInterval??60000),O=Math.min(30000,Math.floor(A*0.8)),j=P.map((H)=>Cf(H,{endpoint:this.options.otlpEndpoint,headers:this.options.otlpHeaders,insecure:this.options.otlpInsecure??!1,protocol:"http/json",interval:A,timeout:O})).filter((H)=>H!==null);if(j.length===0)return null;return new Qf({resource:f,readers:j})}createTracerProvider(f){let P=_(this.options.tracesExporter);if(P.length===0)return null;let A=this.options.otlpTracesEndpoint??this.options.otlpEndpoint,O=this.options.otlpTracesHeaders??this.options.otlpHeaders,j=[];for(let H of P){let J=Mf(H,{endpoint:A,headers:O,insecure:this.options.otlpInsecure??!1,protocol:"http/json"});if(J)j.push(J)}if(j.length===0)return null;return new Vf({resource:f,spanProcessors:j})}createLoggerProvider(f){let P=_(this.options.logsExporter);if(P.length===0)return null;let A=P.map((O)=>{let j=kf(O,{endpoint:this.options.otlpEndpoint,headers:this.options.otlpHeaders,insecure:this.options.otlpInsecure??!1,protocol:"http/json"});if(!j)return null;return new Kf(j,{maxQueueSize:this.options.logMaxQueueSize??2048,maxExportBatchSize:this.options.logBatchSize??512,scheduledDelayMillis:this.options.logBatchTimeoutMs??this.options.logBatchTimeout??5000})}).filter((O)=>O!==null);if(A.length===0)return null;return new Yf({resource:f,processors:A})}}function z(f){let P=new L(f),A=P.createTelemetryService(f),O=()=>{A.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)O();return{provider:P,telemetry:A,emitProviderCreated:O}}function x(f){if(I())return{telemetry:new D(f)};if(f.enabled!==!0)return{telemetry:new Q({...f,distinctId:X(f.distinctId)})};return z(f)}function Lf(f){let{telemetry:P,provider:A,emitProviderCreated:O}=x(f);return{telemetry:P,provider:A,flush:async()=>{let J=A;if(J&&typeof J.forceFlush==="function")try{await J.forceFlush()}catch{}},dispose:async()=>{await Promise.allSettled([P.dispose(),A?.dispose()])},...f.deferProviderCreatedEvent&&O?{emitProviderCreated:O}:{}}}function _(f){if(!f)return[];return(Array.isArray(f)?f:f.split(",")).map((A)=>A.trim()).filter((A)=>A==="console"||A==="otlp")}function kf(f,P){if(f==="console")return new Xf;if(!P.endpoint)return null;let A=k(P.endpoint,"/v1/logs");return new Tf({url:A,headers:P.headers})}function Mf(f,P){if(f==="console")return new Ff(new Bf);if(!P.endpoint)return null;let A=k(P.endpoint,"/v1/traces");return new Rf(new Jf({url:A,headers:P.headers}))}function Cf(f,P){if(f==="console")return new y({exporter:new Zf,exportIntervalMillis:P.interval,exportTimeoutMillis:P.timeout});if(!P.endpoint)return null;let A=k(P.endpoint,"/v1/metrics");return new y({exporter:new $f({url:A,headers:P.headers}),exportIntervalMillis:P.interval,exportTimeoutMillis:P.timeout})}function k(f,P){let A=new URL(f),O=A.pathname.endsWith("/")?A.pathname.slice(0,-1):A.pathname;return A.pathname=O.endsWith(P)?O:`${O}${P}`,A.toString()}export{X as resolveCoreDistinctId,B as resolveCoreDeviceId,z as createOpenTelemetryTelemetryService,x as createConfiguredTelemetryService,Lf as createConfiguredTelemetryHandle,L as OpenTelemetryProvider,Y as OpenTelemetryAdapter};
1
+ import{existsSync as g,mkdirSync as u,readFileSync as c,writeFileSync as m}from"node:fs";import{resolve as d}from"node:path";import{resolveSessionDataDir as l}from"@cerebriline/shared/storage";import{nanoid as p}from"nanoid";import*as r from"node-machine-id";var a="machine-id",q,h=!1;function R(){if(!h)q=E(),h=!0;return q??z()}function Y(f){let j=f?.trim();if(j)return j;let $=E();if($)return $;return z()}function n(){let f=r;return f.machineIdSync??f.default?.machineIdSync}function E(){try{let f=n();if(!f)return;return f().trim()||void 0}catch{return}}function z(){let f=l(),j=d(f,a);try{if(g(j)){let A=c(j,"utf8").trim();if(A.length>0)return A}}catch{}let $=`cl-${p()}`;try{u(f,{recursive:!0}),m(j,$,"utf8")}catch{}return $}class B{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,j){if(!this.isEnabled())return;this.emitLog(f,j,!1)}emitRequired(f,j){this.emitLog(f,j,!0)}recordCounter(f,j,$,A,J=!1){if(!this.meter||!J&&!this.isEnabled())return;let W=this.counters.get(f);if(!W)W=this.meter.createCounter(f,A?{description:A}:void 0),this.counters.set(f,W);W.add(j,this.flattenProperties(this.buildAttributes($)))}recordHistogram(f,j,$,A,J=!1){if(!this.meter||!J&&!this.isEnabled())return;let W=this.histograms.get(f);if(!W)W=this.meter.createHistogram(f,A?{description:A}:void 0),this.histograms.set(f,W);W.record(j,this.flattenProperties(this.buildAttributes($)))}recordGauge(f,j,$,A,J=!1){if(!this.meter||!J&&!this.isEnabled())return;let W=this.buildAttributes($),H=JSON.stringify(W),X=this.gaugeValues.get(f);if(j===null){if(X){if(X.delete(H),X.size===0)this.gaugeValues.delete(f),this.gauges.delete(f)}return}let O=X;if(!O)O=new Map,this.gaugeValues.set(f,O);if(!this.gauges.has(f)){let Z=this.meter.createObservableGauge(f,A?{description:A}:void 0);Z.addCallback((Q)=>{for(let w of this.snapshotGaugeSeries(f))Q.observe(w.value,this.flattenProperties(w.attributes))}),this.gauges.set(f,Z)}O.set(H,{value:j,attributes:W})}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,j,$){if(!this.logger)return;let A=this.flattenProperties(this.buildAttributes(j,$));this.logger.emit({severityText:"INFO",body:f,attributes:A})}buildAttributes(f,j=!1){return{...this.commonProperties,...this.metadata,...f,...this.distinctId?{distinct_id:this.distinctId}:{},...j?{_required:!0}:{}}}snapshotGaugeSeries(f){let j=this.gaugeValues.get(f);if(!j)return[];return Array.from(j.values(),($)=>({value:$.value,attributes:$.attributes?{...$.attributes}:void 0}))}flattenProperties(f,j="",$=new WeakSet,A=0){if(!f)return{};let J={},W=100,H=10;for(let[X,O]of Object.entries(f)){if(X==="__proto__"||X==="constructor"||X==="prototype")continue;let Z=j?`${j}.${X}`:X;if(O===null||O===void 0){J[Z]=String(O);continue}if(Array.isArray(O)){let Q=O.length>W?O.slice(0,W):O;try{J[Z]=JSON.stringify(Q)}catch{J[Z]="[UnserializableArray]"}if(O.length>W)J[`${Z}_truncated`]=!0,J[`${Z}_original_length`]=O.length;continue}if(typeof O==="object"){if(O instanceof Date){J[Z]=O.toISOString();continue}if(O instanceof Error){J[Z]=O.message;continue}if($.has(O)){J[Z]="[Circular]";continue}if(A>=H){J[Z]="[MaxDepthExceeded]";continue}$.add(O),Object.assign(J,this.flattenProperties(O,Z,$,A+1));continue}if(s(O)){J[Z]=O;continue}try{J[Z]=JSON.stringify(O)}catch{J[Z]=String(O)}}return J}}function s(f){return typeof f==="string"||typeof f==="number"||typeof f==="boolean"}import{LangfuseAttributesSpanProcessor as Xf}from"@cerebriline/llms";import{markOtlpTraceRelayProvider as Zf}from"@cerebriline/shared";import{metrics as Kf,trace as Pf}from"@opentelemetry/api";import{logs as Qf}from"@opentelemetry/api-logs";import{OTLPLogExporter as Tf}from"@opentelemetry/exporter-logs-otlp-http";import{OTLPMetricExporter as Yf}from"@opentelemetry/exporter-metrics-otlp-http";import{OTLPTraceExporter as Bf}from"@opentelemetry/exporter-trace-otlp-http";import{resourceFromAttributes as Ff}from"@opentelemetry/resources";import{BatchLogRecordProcessor as Vf,ConsoleLogRecordExporter as Rf,LoggerProvider as Uf}from"@opentelemetry/sdk-logs";import{ConsoleMetricExporter as Lf,MeterProvider as kf,PeriodicExportingMetricReader as G}from"@opentelemetry/sdk-metrics";import{BatchSpanProcessor as Cf,ConsoleSpanExporter as _f,SimpleSpanProcessor as Mf}from"@opentelemetry/sdk-trace-base";import{NodeTracerProvider as wf}from"@opentelemetry/sdk-trace-node";import{ATTR_SERVICE_NAME as qf,ATTR_SERVICE_VERSION as hf}from"@opentelemetry/semantic-conventions";import{mkdirSync as f0,readFileSync as i,statSync as o,writeFileSync as j0}from"node:fs";import{CONFIGURABLE_MODEL_TOOL_NAMES as t}from"@cerebriline/shared";import{resolveGlobalSettingsPath as e}from"@cerebriline/shared/storage";import{z as K}from"zod";import{AGENT_UNEXPECTED_REASONING_TOKENS_EVENT as uf,captureAgentUnexpectedReasoningTokens as cf,captureTaskLifecycleEvent as mf,SDK_ERROR_TELEMETRY_EVENT as df,TASK_CANCELLED_EVENT as lf,TASK_FIRST_CHUNK_RECEIVED_EVENT as pf,TASK_MAX_TOKENS_RECOVERY_EVENT as rf,TASK_PROVIDER_REQUEST_STARTED_EVENT as af,TASK_PROVIDER_STREAM_FAILED_EVENT as nf,TASK_PROVIDER_STREAM_STARTED_EVENT as sf}from"@cerebriline/shared";var U=K.preprocess((f)=>Array.isArray(f)?f.filter((j)=>typeof j==="string").map((j)=>j.trim()).filter(Boolean):void 0,K.array(K.string()).optional()).transform((f)=>{if(!f)return;let j=[...new Set(f)].sort(($,A)=>$.localeCompare(A));return j.length>0?j:void 0}),ff=K.enum(["basic","agentic"]).catch("agentic"),jf=K.partialRecord(K.enum(t),K.object({enabled:K.boolean()}).strip()).optional(),$f=K.record(K.string(),K.object({enabled:K.boolean()}).strip()).optional().catch(void 0),Af=K.enum(["plan","act"]),D=K.object({telemetryOptOut:K.boolean().default(!1).catch(!1),autoUpdateEnabled:K.boolean().default(!0).catch(!0),compactionStrategy:ff.optional(),compactionEnabled:K.boolean().optional().catch(void 0),planActMode:Af.optional().catch(void 0),toolAutoApprove:K.boolean().optional().catch(void 0),tuiTheme:K.string().optional().catch(void 0),disabledTools:U.optional(),tools:jf,disabledPlugins:U.optional(),disabledAgentPlugins:U.optional(),bundledSkills:$f}).strip().transform((f)=>{let j={autoUpdateEnabled:f.autoUpdateEnabled,telemetryOptOut:f.telemetryOptOut};if(f.compactionStrategy)j.compactionStrategy=f.compactionStrategy;if(f.compactionEnabled!==void 0)j.compactionEnabled=f.compactionEnabled;if(f.planActMode)j.planActMode=f.planActMode;if(f.toolAutoApprove!==void 0)j.toolAutoApprove=f.toolAutoApprove;if(f.tuiTheme?.trim())j.tuiTheme=f.tuiTheme.trim();if(f.disabledTools?.length)j.disabledTools=f.disabledTools;if(f.tools&&Object.keys(f.tools).length>0)j.tools=f.tools;if(f.disabledPlugins?.length)j.disabledPlugins=f.disabledPlugins;if(f.disabledAgentPlugins?.length)j.disabledAgentPlugins=f.disabledAgentPlugins;if(f.bundledSkills&&Object.keys(f.bundledSkills).length>0)j.bundledSkills=f.bundledSkills;return j});function F(){return D.parse({})}var L;function Jf(f){if(f.disabledTools)Object.freeze(f.disabledTools);if(f.tools){for(let j of Object.values(f.tools))Object.freeze(j);Object.freeze(f.tools)}if(f.disabledPlugins)Object.freeze(f.disabledPlugins);if(f.disabledAgentPlugins)Object.freeze(f.disabledAgentPlugins);return Object.freeze(f)}function Hf(f){let j;try{j=i(f,"utf8")}catch{return{value:F(),loadFailed:!0}}try{let $=D.safeParse(JSON.parse(j));return $.success?{value:$.data,loadFailed:!1}:{value:F(),loadFailed:!0}}catch{return{value:F(),loadFailed:!0}}}function Wf(){let f=e(),j=o(f,{throwIfNoEntry:!1}),$=j?.mtimeMs??0,A=j?.size??0,J=L;if(J&&J.path===f&&J.mtimeMs===$&&J.size===A)return J;let W=j?Hf(f):{value:F(),loadFailed:!1},H=Jf(W.value);return L={path:f,mtimeMs:$,size:A,value:H,loadFailed:W.loadFailed},L}function Of(){return Wf().value}function I(){return Of().telemetryOptOut}class k{name;logger;enabled;constructor(f={}){this.name=f.name??"TelemetryLoggerSink",this.logger=f.logger,this.enabled=f.enabled??!0}emit(f,j){if(!this.isEnabled())return;this.logger?.log("telemetry.event",{telemetrySink:this.name,event:f,properties:j})}emitRequired(f,j){this.logger?.log("telemetry.required_event",{telemetrySink:this.name,severity:"warn",event:f,properties:j})}recordCounter(f,j,$,A,J){if(!J&&!this.isEnabled())return;this.logger?.debug("telemetry.metric",{telemetrySink:this.name,instrument:"counter",name:f,value:j,attributes:$,description:A,required:J===!0})}recordHistogram(f,j,$,A,J){if(!J&&!this.isEnabled())return;this.logger?.debug("telemetry.metric",{telemetrySink:this.name,instrument:"histogram",name:f,value:j,attributes:$,description:A,required:J===!0})}recordGauge(f,j,$,A,J){if(!J&&!this.isEnabled())return;this.logger?.debug("telemetry.metric",{telemetrySink:this.name,instrument:"gauge",name:f,value:j,attributes:$,description:A,required:J===!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 k({logger:f.logger}));this.metadata={...f.metadata??{}},this.distinctId=f.distinctId,this.deviceId=f.deviceId??R(),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 j=this.buildAttributes(f.properties);for(let $ of this.adapters)$.emit(f.event,j)}captureRequired(f,j){let $=this.buildAttributes(j);for(let A of this.adapters)A.emitRequired(f,$)}recordCounter(f,j,$,A,J=!1){let W=this.buildAttributes($);for(let H of this.adapters)H.recordCounter(f,j,W,A,J)}recordHistogram(f,j,$,A,J=!1){let W=this.buildAttributes($);for(let H of this.adapters)H.recordHistogram(f,j,W,A,J)}recordGauge(f,j,$,A,J=!1){let W=this.buildAttributes($);for(let H of this.adapters)H.recordGauge(f,j,W,A,J)}async flush(){await Promise.all(this.adapters.map((f)=>f.flush()))}async dispose(){await Promise.all(this.adapters.map((f)=>f.dispose()))}buildAttributes(f){let j=typeof f?.distinct_id==="string"&&f.distinct_id.trim()?f.distinct_id.trim():this.distinctId,$={...this.commonProperties,...this.metadata,...f,...j?{distinct_id:j}:{},device_id:this.deviceId};return Object.fromEntries(Object.entries($).filter(([,A])=>A!==void 0))}}class x{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,j){this.resolveProperties(j)}recordCounter(){}recordHistogram(){}recordGauge(){}async flush(){}async dispose(){}resolveProperties(f){let j=typeof f?.distinct_id==="string"&&f.distinct_id.trim()?f.distinct_id.trim():this.distinctId,$={...this.commonProperties,...this.metadata,...f,...j?{distinct_id:j}:{}};return Object.fromEntries(Object.entries($).filter(([,A])=>A!==void 0))}}class _{meterProvider;loggerProvider;tracerProvider;options;constructor(f={}){this.options=f;let j=Ff({[qf]:f.serviceName??"cline",...f.serviceVersion?{[hf]:f.serviceVersion}:{}});if(this.meterProvider=this.createMeterProvider(j),this.loggerProvider=this.createLoggerProvider(j),this.tracerProvider=this.createTracerProvider(j),this.meterProvider)Kf.setGlobalMeterProvider(this.meterProvider);if(this.loggerProvider)Qf.setGlobalLoggerProvider(this.loggerProvider);if(this.tracerProvider)this.tracerProvider.register()}getTracer(f="cline",j){return Pf.getTracer(f,j??this.options.serviceVersion)}createAdapter(f){return new B({...f,meterProvider:this.meterProvider,loggerProvider:this.loggerProvider})}createTelemetryService(f){let j=this.createAdapter({name:f.name,enabled:this.options.enabled,metadata:f.metadata});return new V({...f,adapters:[j],distinctId:Y(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 j=C(this.options.metricsExporter);if(j.length===0)return null;let $=Math.max(1000,this.options.metricExportIntervalMs??this.options.metricExportInterval??60000),A=Math.min(30000,Math.floor($*0.8)),J=j.map((W)=>If(W,{endpoint:this.options.otlpEndpoint,headers:this.options.otlpHeaders,insecure:this.options.otlpInsecure??!1,protocol:"http/json",interval:$,timeout:A})).filter((W)=>W!==null);if(J.length===0)return null;return new kf({resource:f,readers:J})}createTracerProvider(f){let j=C(this.options.tracesExporter);if(j.length===0)return null;let $=this.options.otlpTracesEndpoint??this.options.otlpEndpoint,A=this.options.otlpTracesHeaders??this.options.otlpHeaders,J=[],W=!1;for(let X of j){let O=Df(X,{endpoint:$,headers:A,insecure:this.options.otlpInsecure??!1,protocol:"http/json"});if(O){if(J.push(O),X!=="console")W=!0}}if(J.length===0)return null;let H=new wf({resource:f,spanProcessors:W?[new Xf,...J]:J});if(W)Zf(H);return H}createLoggerProvider(f){let j=C(this.options.logsExporter);if(j.length===0)return null;let $=j.map((A)=>{let J=zf(A,{endpoint:this.options.otlpEndpoint,headers:this.options.otlpHeaders,insecure:this.options.otlpInsecure??!1,protocol:"http/json"});if(!J)return null;return new Vf(J,{maxQueueSize:this.options.logMaxQueueSize??2048,maxExportBatchSize:this.options.logBatchSize??512,scheduledDelayMillis:this.options.logBatchTimeoutMs??this.options.logBatchTimeout??5000})}).filter((A)=>A!==null);if($.length===0)return null;return new Uf({resource:f,processors:$})}}function N(f){let j=new _(f),$=j.createTelemetryService(f),A=()=>{$.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:j,telemetry:$,emitProviderCreated:A}}function y(f){if(I())return{telemetry:new x(f)};if(f.enabled!==!0)return{telemetry:new V({...f,distinctId:Y(f.distinctId)})};return N(f)}function Ef(f){let{telemetry:j,provider:$,emitProviderCreated:A}=y(f);return{telemetry:j,provider:$,flush:async()=>{let H=$;if(H&&typeof H.forceFlush==="function")try{await H.forceFlush()}catch{}},dispose:async()=>{await Promise.allSettled([j.dispose(),$?.dispose()])},...f.deferProviderCreatedEvent&&A?{emitProviderCreated:A}:{}}}function C(f){if(!f)return[];return(Array.isArray(f)?f:f.split(",")).map(($)=>$.trim()).filter(($)=>$==="console"||$==="otlp")}function zf(f,j){if(f==="console")return new Rf;if(!j.endpoint)return null;let $=M(j.endpoint,"/v1/logs");return new Tf({url:$,headers:j.headers})}function Df(f,j){if(f==="console")return new Mf(new _f);if(!j.endpoint)return null;let $=M(j.endpoint,"/v1/traces");return new Cf(new Bf({url:$,headers:j.headers}))}function If(f,j){if(f==="console")return new G({exporter:new Lf,exportIntervalMillis:j.interval,exportTimeoutMillis:j.timeout});if(!j.endpoint)return null;let $=M(j.endpoint,"/v1/metrics");return new G({exporter:new Yf({url:$,headers:j.headers}),exportIntervalMillis:j.interval,exportTimeoutMillis:j.timeout})}function M(f,j){let $=new URL(f),A=$.pathname.endsWith("/")?$.pathname.slice(0,-1):$.pathname;return $.pathname=A.endsWith(j)?A:`${A}${j}`,$.toString()}import{SESSION_STATUS_VALUES as D0}from"@cerebriline/shared";var T={CORE:"core",CLI:"cli",SUBAGENT:"subagent",DESKTOP:"desktop",KANBAN:"kanban",API:"api",WEB:"web",VSCODE:"vscode",ENTERPRISE:"enterprise",IDE:"ide",JETBRAINS:"jetbrains",NEOVIM:"neovim",UNKNOWN:"unknown"};function b(f){let j=[f?.name,f?.platform].filter(($)=>typeof $==="string").join(" ").toLowerCase();if(!j)return;if(j.includes("vscode")||j.includes("visual studio code"))return T.VSCODE;if(j.includes("jetbrains")||j.includes("webstorm")||j.includes("intellij")||j.includes("pycharm")||j.includes("goland")||j.includes("clion")||j.includes("rider")||j.includes("android studio"))return T.JETBRAINS;if(j.includes("neovim"))return T.NEOVIM;if(j.includes("kanban"))return T.KANBAN;if(j.includes("desktop"))return T.DESKTOP;if(j.includes("cline-platform"))return T.WEB;if(j.includes("cline-cli")||j.includes("cline-acp"))return T.CLI;if(j.includes("cline-sdk")||j.includes("cline-core"))return T.CORE;return}function P(f){let j=f?.trim();return j?j:void 0}function S(f){let j=f.client,$=b(j)??P(f.source),A=P(j.version),J=P(j.platform)??P(j.name),W=P(j.platformVersion)??A,H={cline_type:$,extension_version:A,platform:J,platform_version:W};if(f.user?.accountId===void 0)return H;let X=typeof f.user.accountId==="string"?P(f.user.accountId):void 0;return{...H,distinct_id:X??P(f.user.distinctId),user_id:X,account_id:X,account_email:X?P(f.user.email):void 0,organization_id:X?P(f.user.organizationId):void 0}}function v(f,j){let $={},A={},J,W=(H)=>({...j,...A,...$,...H,...J?{distinct_id:J}:{}});return{setDistinctId(H){J=P(H)},setMetadata(H){$={...H}},updateMetadata(H){$={...$,...H}},setCommonProperties(H){A={...H}},updateCommonProperties(H){A={...A,...H}},isEnabled:()=>f.isEnabled(),capture:(H)=>f.capture({event:H.event,properties:W(H.properties)}),captureRequired:(H,X)=>f.captureRequired(H,W(X)),recordCounter:(H,X,O,Z,Q)=>f.recordCounter(H,X,W(O),Z,Q),recordHistogram:(H,X,O,Z,Q)=>f.recordHistogram(H,X,W(O),Z,Q),recordGauge:(H,X,O,Z,Q)=>f.recordGauge(H,X,W(O),Z,Q),flush:()=>f.flush(),dispose:async()=>{}}}function Gf(f,j){return v(f,S(j))}export{Y as resolveCoreDistinctId,R as resolveCoreDeviceId,S as resolveClientTelemetryProperties,v as createScopedTelemetryService,N as createOpenTelemetryTelemetryService,y as createConfiguredTelemetryService,Ef as createConfiguredTelemetryHandle,Gf as createClientScopedTelemetryService,_ as OpenTelemetryProvider,B as OpenTelemetryAdapter};
@@ -0,0 +1,31 @@
1
+ import type { ClientContext, ITelemetryService, TelemetryProperties, UserContext } from "@cerebriline/shared";
2
+ /**
3
+ * Client identity that can safely cross a runtime boundary and be attached to
4
+ * telemetry emitted by the process that actually executes a session.
5
+ */
6
+ export interface ClientTelemetryContext {
7
+ client: ClientContext;
8
+ source?: string;
9
+ user?: UserContext;
10
+ }
11
+ /**
12
+ * Converts the shared client context into the established cross-surface
13
+ * analytics dimensions. Event-specific fields still take precedence.
14
+ */
15
+ export declare function resolveClientTelemetryProperties(context: ClientTelemetryContext): TelemetryProperties;
16
+ /**
17
+ * A non-owning view over a host telemetry service. It adds immutable
18
+ * per-session properties without mutating the host singleton, which is
19
+ * essential for a Hub process that can execute sessions from several clients
20
+ * concurrently.
21
+ *
22
+ * The returned view never disposes the parent. The process that created the
23
+ * parent telemetry service remains responsible for its lifecycle.
24
+ */
25
+ export declare function createScopedTelemetryService(parent: ITelemetryService, properties: TelemetryProperties): ITelemetryService;
26
+ /**
27
+ * Scopes a host telemetry singleton to one runtime client. This is the
28
+ * reusable bridge used by Hub-hosted sessions; local clients that already
29
+ * provide their own telemetry service do not need it.
30
+ */
31
+ export declare function createClientScopedTelemetryService(parent: ITelemetryService, context: ClientTelemetryContext): ITelemetryService;
@@ -1,4 +1,38 @@
1
1
  import type { WorkspaceInfo } from "@cerebriline/shared";
2
+ export type GitCommand = (args: readonly string[], options: {
3
+ cwd: string;
4
+ signal?: AbortSignal;
5
+ }) => Promise<{
6
+ stdout: string;
7
+ stderr?: string;
8
+ }>;
9
+ export declare function gitCommandErrorMessage(error: unknown): string;
10
+ export declare function gitCommandExitCode(error: unknown): number | undefined;
11
+ /**
12
+ * Shared Git queries, without metadata fallback or cloud-handoff policy.
13
+ * Display branches retain simple-git's detached/unborn semantics; symbolic
14
+ * branches are strict and preserve Git exit codes for callers that require one.
15
+ * Commands are lazy so metadata reads never collect status or contact a remote.
16
+ * Structured display queries use simple-git; raw queries use the injectable
17
+ * runner to retain exit codes, timeouts, and cancellation for strict checks.
18
+ */
19
+ export declare function createWorkspaceGitReader(input: {
20
+ cwd: string;
21
+ git?: GitCommand;
22
+ signal?: AbortSignal;
23
+ }): {
24
+ isInsideWorkTree(): Promise<boolean>;
25
+ remotes: () => import("simple-git").Response<import("simple-git").RemoteWithRefs[]>;
26
+ displayBranch: () => Promise<string>;
27
+ symbolicBranch: () => Promise<string>;
28
+ headSha: () => Promise<string>;
29
+ workspacePrefix: () => Promise<string>;
30
+ worktreeStatus: () => Promise<string>;
31
+ branchRemote: (branch: string) => Promise<string>;
32
+ branchMergeRef: (branch: string) => Promise<string>;
33
+ remoteUrl: (remote: string) => Promise<string>;
34
+ remoteRefs: (remote: string, ref: string) => Promise<string>;
35
+ };
2
36
  export interface WorkspaceInfoDiagnostics {
3
37
  info: WorkspaceInfo;
4
38
  vcsType: "git" | "none";
@@ -2,6 +2,11 @@ import type { ITelemetryService, WorkspaceInfo } from "@cerebriline/shared";
2
2
  export interface WorkspaceLifecycleTelemetryInput {
3
3
  telemetry?: ITelemetryService;
4
4
  rootPath: string;
5
+ /**
6
+ * Optional client identity used for de-duplication in a shared runtime
7
+ * process. The same workspace still emits once per client surface.
8
+ */
9
+ dedupeScope?: string;
5
10
  workspaceInfo?: WorkspaceInfo;
6
11
  rootCount?: number;
7
12
  vcsType?: "git" | "none";
@@ -0,0 +1,7 @@
1
+ export declare function createForkSessionMetadata(input: {
2
+ metadata?: Record<string, unknown> | null;
3
+ forkedFromSessionId: string;
4
+ forkedAt: string;
5
+ source: string;
6
+ beforeRunCount?: number;
7
+ }): Record<string, unknown>;
@@ -18,5 +18,12 @@ export declare function createSessionCompactionState(input: {
18
18
  systemPrompt?: string;
19
19
  updatedAt?: string;
20
20
  }): SessionCompactionState;
21
- export declare function projectSessionCompactionState(state: SessionCompactionState, sourceMessages: readonly MessageWithMetadata[]): MessageWithMetadata[] | undefined;
21
+ export declare function projectSessionCompactionState(state: SessionCompactionState, sourceMessages: readonly MessageWithMetadata[],
22
+ /**
23
+ * The same transcript as it is about to be sent, when a stage ahead of
24
+ * compaction rewrote a message in it. The state is matched against
25
+ * `sourceMessages`; the tail that follows the compacted part is taken from
26
+ * here, so the rewrite is not undone by the projection.
27
+ */
28
+ tailMessages?: readonly MessageWithMetadata[]): MessageWithMetadata[] | undefined;
22
29
  export declare function parseSessionCompactionState(value: unknown): SessionCompactionState | undefined;
@@ -8,7 +8,7 @@
8
8
  * tool-result truncation and outdated-file-content rewrite for compaction.
9
9
  * Per-instance caches make this host state.
10
10
  */
11
- import { type MediaBudgetOptions, type Message } from "@cerebriline/shared";
11
+ import { type MediaBudgetOptions, type Message, type ToolResultContent } from "@cerebriline/shared";
12
12
  export declare const DEFAULT_MAX_TOOL_RESULT_CHARS = 32000;
13
13
  export declare const DEFAULT_MAX_FILE_CONTENT_CHARS = 50000;
14
14
  export declare const DEFAULT_MAX_TOTAL_TEXT_BYTES = 6000000;
@@ -49,6 +49,10 @@ export declare const MESSAGE_BUILDER_LIMIT_ENV: {
49
49
  readonly minOutdatedRewriteBytes: "CLINE_MESSAGE_BUILDER_MIN_OUTDATED_REWRITE_BYTES";
50
50
  };
51
51
  export interface MessageBuilderOptions {
52
+ /** Synchronous Core-owned recovery lookup; undefined leaves the normal result projection unchanged. */
53
+ getToolResultRecovery?: (result: ToolResultContent) => {
54
+ uri?: string;
55
+ } | undefined;
52
56
  maxToolResultChars?: number;
53
57
  maxFileContentChars?: number;
54
58
  maxTotalTextBytes?: number;
@@ -67,6 +71,9 @@ export declare function getMessageBuilderOptionsFromEnv(env?: Record<string, str
67
71
  * Builds an API-safe message copy without mutating original conversation history.
68
72
  */
69
73
  export declare class MessageBuilder {
74
+ private readonly recoveryNotices;
75
+ private readonly getToolResultRecovery?;
76
+ private recoveryNoticeBytes;
70
77
  private indexedMessageCount;
71
78
  private indexedTailRef;
72
79
  private readonly toolNameByIdCache;
@@ -52,6 +52,7 @@ export declare class UnifiedSessionPersistenceService {
52
52
  title?: string | null;
53
53
  }): Promise<{
54
54
  updated: boolean;
55
+ metadata?: Record<string, unknown> | null;
55
56
  }>;
56
57
  queueSpawnRequest(event: HookEventPayload): Promise<void>;
57
58
  upsertSubagentSession(input: import("../models/session-row").UpsertSubagentInput): Promise<string | undefined>;
@@ -73,7 +74,9 @@ export declare class UnifiedSessionPersistenceService {
73
74
  handleSubAgentEnd(rootSessionId: string, context: SubAgentEndContext): Promise<void>;
74
75
  private isPidAlive;
75
76
  private reconcileDeadRunningSession;
76
- listSessions(limit?: number): Promise<SessionRow[]>;
77
+ listSessions(limit?: number, options?: {
78
+ rootOnly?: boolean;
79
+ }): Promise<SessionRow[]>;
77
80
  /**
78
81
  * Lightweight, effectively unbounded listing of session ids + metadata
79
82
  * (no manifest reads, no dead-session reconciliation). listSessions caps
@@ -0,0 +1,30 @@
1
+ import type { ImageContent } from "@cerebriline/shared";
2
+ export declare const TOOL_RESULT_CACHE_MAX_BYTES: number;
3
+ export declare const TOOL_RESULT_CACHE_IDLE_ITERATIONS = 5;
4
+ export declare const TOOL_RESULT_CACHE_MISS = "Cache not found. Make a new tool call for the latest result again if needed. DO NOT repeat side-effecting actions to recover output.";
5
+ /** Session-owned volatile text cache. Looking up a URI never extends its lifetime. */
6
+ export declare class ToolResultCache {
7
+ private readonly sessionId;
8
+ private readonly maxBytes;
9
+ private readonly entries;
10
+ private readonly referencesByToolCall;
11
+ private iteration;
12
+ private bytes;
13
+ constructor(sessionId: string, maxBytes?: number);
14
+ store(toolCallId: string, text: string): string | undefined;
15
+ uriFor(toolCallId: string): string | undefined;
16
+ read(uri: string): string;
17
+ advanceIteration(): void;
18
+ clear(): void;
19
+ private remove;
20
+ }
21
+ /** Size and truncate the persisted representation sent to the model. */
22
+ export declare function prepareToolResultPreview(content: unknown): {
23
+ text: string | undefined;
24
+ images: ImageContent[];
25
+ };
26
+ /** YAML is only the readable recovery copy, not the truncation threshold. */
27
+ export declare function prepareToolResultRecovery(output: unknown): {
28
+ text: string | undefined;
29
+ images: ImageContent[];
30
+ };
@@ -1,4 +1,5 @@
1
1
  import type * as LlmsProviders from "@cerebriline/llms";
2
+ import type { ITelemetryService } from "@cerebriline/shared";
2
3
  import type { CheckpointEntry, CheckpointMetadata } from "../hooks/checkpoint-hooks";
3
4
  import type { RestoreSessionInput } from "../runtime/host/runtime-host";
4
5
  import type { SessionRecord } from "../types/sessions";
@@ -44,6 +45,13 @@ export interface SessionCheckpointRestoreInput<TRestoreStartInput, TStartInput,
44
45
  applyWorkspaceCheckpoint?: (cwd: string, checkpoint: CheckpointEntry) => Promise<void>;
45
46
  beginWorkspaceRestoreTransaction?: (cwd: string) => Promise<WorktreeRestoreTransaction>;
46
47
  retainCheckpointRefs?: (cwd: string, sessionId: string, history: CheckpointEntry[]) => Promise<void>;
48
+ /**
49
+ * Emits one `checkpoint.restore` event per restore attempt. Restores are
50
+ * rare and destructive, so field visibility matters: outcome, duration
51
+ * (the worktree transaction hashes all untracked files), and the
52
+ * checkpoint kind. Never file paths or contents.
53
+ */
54
+ telemetry?: Pick<ITelemetryService, "capture">;
47
55
  }
48
56
  export declare class SessionVersioningService {
49
57
  restoreCheckpoint<TRestoreStartInput, TStartInput, TStartResult>(input: SessionCheckpointRestoreInput<TRestoreStartInput, TStartInput, TStartResult>): Promise<SessionCheckpointRestoreResult<TStartResult>>;
@@ -31,12 +31,10 @@ export declare class SessionManifestStore {
31
31
  path: string;
32
32
  manifest?: SessionManifest;
33
33
  };
34
+ readSessionRowFromManifest(sessionId: string): SessionRow | undefined;
34
35
  /**
35
36
  * 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.
37
+ * on-disk manifest when the index was rebuilt or the artifacts were restored.
40
38
  */
41
39
  private resolveSessionRow;
42
40
  persistSessionMessages(sessionId: string, messages: LlmsProviders.MessageWithMetadata[], systemPrompt?: string): Promise<void>;