@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.
- package/assets/prompt-templates/claude.md +2 -0
- package/assets/prompt-templates/deepseek.md +1 -0
- package/assets/prompt-templates/default.md +2 -1
- package/assets/prompt-templates/kimi-k3.md +1 -0
- package/assets/prompt-templates/kimi.md +1 -0
- package/assets/prompt-templates/minimax.md +2 -0
- package/assets/prompt-templates/nemotron.md +1 -0
- package/assets/skills/browser-automation/SKILL.md +113 -0
- package/dist/ClineCore.d.ts +9 -0
- package/dist/account/index.d.ts +1 -0
- package/dist/account/telemetry.d.ts +22 -0
- package/dist/cloud/api.d.ts +122 -0
- package/dist/cloud/controller.d.ts +172 -0
- package/dist/cloud/index.d.ts +9 -0
- package/dist/cloud/index.js +21 -0
- package/dist/cloud/models.d.ts +9 -0
- package/dist/cloud/repositories.d.ts +21 -0
- package/dist/cloud/snapshots.d.ts +22 -0
- package/dist/cloud/state.d.ts +13 -0
- package/dist/cloud/types.d.ts +84 -0
- package/dist/cron/events/cron-event-ingress.d.ts +4 -2
- package/dist/cron/runner/cron-runner.d.ts +5 -2
- package/dist/cron/service/cron-service.d.ts +2 -1
- package/dist/cron/service/schedule-service.d.ts +2 -1
- package/dist/cron/store/sqlite-cron-store.d.ts +7 -1
- package/dist/extensions/composio/composio-meta-tools.d.ts +39 -0
- package/dist/extensions/composio/composio-tools-extension.d.ts +13 -0
- package/dist/extensions/context/agentic-compaction.d.ts +1 -1
- package/dist/extensions/context/cap-thoughts.d.ts +39 -0
- package/dist/extensions/context/compaction-shared.d.ts +76 -1
- package/dist/extensions/context/compaction.d.ts +75 -3
- package/dist/extensions/mcp/client.d.ts +1 -1
- package/dist/extensions/tools/definitions.d.ts +5 -5
- package/dist/extensions/tools/executors/bash.d.ts +26 -0
- package/dist/extensions/tools/executors/index.d.ts +1 -1
- package/dist/extensions/tools/index.d.ts +1 -1
- package/dist/extensions/tools/task-progress.d.ts +37 -0
- package/dist/extensions/tools/team/index.d.ts +1 -0
- package/dist/extensions/tools/team/multi-agent.d.ts +48 -0
- package/dist/extensions/tools/team/persistence-policy.d.ts +56 -0
- package/dist/extensions/tools/team/runtime.d.ts +1 -1
- package/dist/extensions/tools/team/sanitize-team-name.d.ts +5 -0
- package/dist/extensions/tools/team/team-tools.d.ts +1 -1
- package/dist/hooks/checkpoint-hooks.d.ts +23 -1
- package/dist/hooks/hook-file-hooks.d.ts +27 -0
- package/dist/hooks/subprocess-runner.d.ts +23 -0
- package/dist/hooks/subprocess.d.ts +10 -0
- package/dist/hub/client/index.d.ts +29 -3
- package/dist/hub/client/session-client.d.ts +0 -3
- package/dist/hub/daemon/bind-diagnostics.d.ts +16 -0
- package/dist/hub/daemon/entry.js +689 -640
- package/dist/hub/daemon/index.d.ts +17 -8
- package/dist/hub/discovery/index.d.ts +1 -0
- package/dist/hub/index.js +675 -627
- package/dist/hub/runtime-host/hub-runtime-host.d.ts +4 -2
- package/dist/hub/server/handlers/session-handlers.d.ts +6 -1
- package/dist/index.d.ts +21 -11
- package/dist/index.js +1032 -964
- package/dist/remote/remote-environments.d.ts +155 -0
- package/dist/remote/remote-helper-entry.d.ts +1 -0
- package/dist/remote/remote-helper-entry.js +5 -0
- package/dist/remote/remote-helper.d.ts +29 -0
- package/dist/remote/remote-helper.js +4 -0
- package/dist/remote/shell-path.d.ts +88 -0
- package/dist/runtime/host/local-runtime-host.d.ts +2 -2
- package/dist/runtime/host/runtime-host.d.ts +13 -1
- package/dist/runtime/orchestration/oauth-refresh-lock.d.ts +6 -0
- package/dist/runtime/orchestration/session-runtime-orchestrator.d.ts +7 -0
- package/dist/runtime/orchestration/team-persistence-writer.d.ts +65 -0
- package/dist/runtime/safety/rules.d.ts +11 -0
- package/dist/runtime/turn-queue/pending-prompt-service.d.ts +1 -0
- package/dist/services/agent-events.d.ts +1 -0
- package/dist/services/cloud-handoff/git-preflight.d.ts +24 -0
- package/dist/services/cloud-handoff/index.d.ts +4 -0
- package/dist/services/cloud-handoff/metadata.d.ts +7 -0
- package/dist/services/cloud-handoff/transcript.d.ts +5 -0
- package/dist/services/cloud-handoff/types.d.ts +35 -0
- package/dist/services/feature-flags/FeatureFlagsService.d.ts +2 -0
- package/dist/services/feature-flags/cline-account-feature-flags.d.ts +5 -0
- package/dist/services/llms/cline-recommended-models.d.ts +1 -0
- package/dist/services/llms/handler-factory.d.ts +12 -0
- package/dist/services/llms/provider-defaults.d.ts +1 -1
- package/dist/services/llms/provider-settings.d.ts +19 -17
- package/dist/services/local-runtime-bootstrap.d.ts +7 -0
- package/dist/services/mcp-install.d.ts +9 -0
- package/dist/services/plugin-commands.d.ts +28 -0
- package/dist/services/providers/local-provider-registry.d.ts +8 -3
- package/dist/services/providers/local-provider-service.d.ts +20 -10
- package/dist/services/providers/model-source.d.ts +6 -1
- package/dist/services/providers/provider-config-fields.d.ts +11 -0
- package/dist/services/session-import/claude-code.d.ts +1 -1
- package/dist/services/session-import/paths.d.ts +9 -0
- package/dist/services/storage/file-team-store.d.ts +10 -4
- package/dist/services/storage/sqlite-team-store.d.ts +48 -5
- package/dist/services/storage/team-store.d.ts +1 -0
- package/dist/services/telemetry/core-events.d.ts +97 -5
- package/dist/services/telemetry/index.d.ts +1 -0
- package/dist/services/telemetry/index.js +1 -1
- package/dist/services/telemetry/scoped-telemetry.d.ts +31 -0
- package/dist/services/workspace/workspace-manifest.d.ts +34 -0
- package/dist/services/workspace/workspace-telemetry.d.ts +5 -0
- package/dist/session/fork-metadata.d.ts +7 -0
- package/dist/session/models/session-compaction.d.ts +8 -1
- package/dist/session/services/message-builder.d.ts +8 -1
- package/dist/session/services/persistence-service.d.ts +4 -1
- package/dist/session/services/tool-result-cache.d.ts +30 -0
- package/dist/session/session-versioning-service.d.ts +8 -0
- package/dist/session/stores/session-manifest-store.d.ts +2 -4
- package/dist/session/team/team-session-coordinator.d.ts +3 -1
- package/dist/tasks/task-tool.d.ts +2 -2
- package/dist/types/provider-settings.d.ts +11 -0
- package/dist/types/session.d.ts +2 -0
- package/dist/types/storage.d.ts +22 -1
- package/package.json +16 -4
- package/dist/cron/runner/resource-limiter.d.ts +0 -8
- package/dist/services/storage/team-events-retention.d.ts +0 -25
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-chat authentication for Composio connectors.
|
|
3
|
+
*
|
|
4
|
+
* The Cline API creates a per-user Composio tool-router session scoped to the
|
|
5
|
+
* project's enabled auth configs (`POST /api/v1/connectors/meta-tools/sessions`)
|
|
6
|
+
* and returns the schemas of its allowlisted meta tools: COMPOSIO_SEARCH_TOOLS
|
|
7
|
+
* finds tools across those toolkits, COMPOSIO_MANAGE_CONNECTIONS returns a
|
|
8
|
+
* hosted Connect Link the agent surfaces in chat, COMPOSIO_WAIT_FOR_CONNECTIONS
|
|
9
|
+
* blocks until the user finishes, and COMPOSIO_MULTI_EXECUTE_TOOL runs the
|
|
10
|
+
* tools search found — no new session needed after connecting.
|
|
11
|
+
* Credentials never pass through Cline or the model — only the link does.
|
|
12
|
+
* Executions go back through the proxy with the session id
|
|
13
|
+
* (`POST /api/v1/connectors/meta-tools/{slug}/execute`), which checks that the
|
|
14
|
+
* session belongs to the caller.
|
|
15
|
+
*/
|
|
16
|
+
export declare const CONNECTORS_API_PATH = "/api/v1/connectors";
|
|
17
|
+
export type ConnectorsAuth = {
|
|
18
|
+
baseUrl: string;
|
|
19
|
+
token: string;
|
|
20
|
+
};
|
|
21
|
+
export type ComposioMetaTool = {
|
|
22
|
+
slug: string;
|
|
23
|
+
name?: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
input_parameters?: Record<string, unknown>;
|
|
26
|
+
};
|
|
27
|
+
export type ComposioMetaToolSession = {
|
|
28
|
+
sessionId: string;
|
|
29
|
+
tools: ComposioMetaTool[];
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Creates a meta-tool session, or returns undefined when in-chat auth is
|
|
33
|
+
* unavailable: no connectable toolkits (404), a proxy without the endpoint, or
|
|
34
|
+
* any network failure. Callers then run without the meta tools.
|
|
35
|
+
*/
|
|
36
|
+
export declare function createComposioMetaToolSession(auth: ConnectorsAuth, options?: {
|
|
37
|
+
log?: (message: string) => void;
|
|
38
|
+
}): Promise<ComposioMetaToolSession | undefined>;
|
|
39
|
+
export declare function executeComposioMetaTool(auth: ConnectorsAuth, sessionId: string, slug: string, input: unknown): Promise<unknown>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AgentExtension, BasicLogger } from "@cerebriline/shared";
|
|
2
|
+
export declare function resolveComposioToolsStatePath(accountId: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* Builds the extension for the current connector state, or undefined when
|
|
5
|
+
* there is nothing to register (no state file, or no connected toolkit with
|
|
6
|
+
* tools) — sessions without connectors pay one file read.
|
|
7
|
+
*
|
|
8
|
+
* The state is read once here, at session-bootstrap time, so a session's
|
|
9
|
+
* tool set is frozen at start exactly like the previous plugin's was.
|
|
10
|
+
*/
|
|
11
|
+
export declare function createComposioToolsExtension(options?: {
|
|
12
|
+
logger?: BasicLogger;
|
|
13
|
+
}): Promise<AgentExtension | undefined>;
|
|
@@ -25,7 +25,7 @@ export declare function buildAgenticSummaryInputBudget(options: {
|
|
|
25
25
|
export declare const SUMMARIZER_SYSTEM_PROMPTS: {
|
|
26
26
|
readonly tail: "You are re-telling your own recent work in your own voice, because the earlier part of your transcript is about to be discarded and what you write takes its place directly in front of the turns that remain. Match the prose of those turns. Keep every specific — names, paths, quoted wording, errors, numbers — that you would otherwise have to rediscover.";
|
|
27
27
|
readonly full: "You write the state record for a working session of any kind. The transcript you are given is about to be discarded, so what you write is the only record that remains. Follow the requested structure exactly, section for section, and keep every specific — names, paths, quoted wording, errors, numbers — that whoever continues would otherwise have to rediscover.";
|
|
28
|
-
readonly retrospective: "You are
|
|
28
|
+
readonly retrospective: "You are saying, in your own voice and in the present tense, how your work on this task is going, from your own reasoning on the part of it that is about to be discarded. This is what you think of it, not a record — what happened is written up separately. Plain prose, first person, short: only what you want in mind before the next hour of this task.";
|
|
29
29
|
};
|
|
30
30
|
/**
|
|
31
31
|
* The model calls a compaction is about to make, counted before it makes them.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thoughts the harness writes into the retrospective, in the model's voice.
|
|
3
|
+
*
|
|
4
|
+
* The retrospective is the model's own judgement of how the work went, and it
|
|
5
|
+
* is blind to the events that cost the most, because those are exactly the
|
|
6
|
+
* turns it never got to read: a reply discarded at the output limit takes its
|
|
7
|
+
* reasoning with it, a looped block is removed, a call nothing could parse
|
|
8
|
+
* never ran. The harness saw every one of them. So it says so, in the first
|
|
9
|
+
* person and the present tense like the text it sits in, as something the
|
|
10
|
+
* model has noticed about its own work -- and draws the one conclusion all of
|
|
11
|
+
* them share: the unit of work is too large.
|
|
12
|
+
*
|
|
13
|
+
* Measured on the runs this was built from (pandorum, 2026-10-10, v9-agentic):
|
|
14
|
+
* 13 replies discarded at the output limit, 21 unreadable calls and 4 looped
|
|
15
|
+
* turns across 22 sessions, nearly all on a turn that thought at length and
|
|
16
|
+
* then wrote one very large edit.
|
|
17
|
+
*/
|
|
18
|
+
import type { MessageWithMetadata } from "@cerebriline/shared";
|
|
19
|
+
export interface CapEvents {
|
|
20
|
+
/** Replies thrown away because they ended at the output limit. */
|
|
21
|
+
outputLimit: number;
|
|
22
|
+
/** Turns whose reasoning ended because the thinking budget ran out. */
|
|
23
|
+
thinkingBudget: number;
|
|
24
|
+
/** Turns whose reasoning collapsed into repetition. */
|
|
25
|
+
loops: number;
|
|
26
|
+
/** Tool calls that came back as text and never ran. */
|
|
27
|
+
unreadableCalls: number;
|
|
28
|
+
}
|
|
29
|
+
/** Count the events since the last compaction, from what the messages carry. */
|
|
30
|
+
export declare function countCapEvents(messages: readonly MessageWithMetadata[], budgetMessage?: string): CapEvents;
|
|
31
|
+
/**
|
|
32
|
+
* The thought, or nothing when there is nothing to have noticed.
|
|
33
|
+
*
|
|
34
|
+
* One paragraph. It names what happened with its count, says what it cost,
|
|
35
|
+
* and ends on what to do instead -- smaller units, shorter reasoning, acting
|
|
36
|
+
* in sequence. The advice is the same whichever event fired, because the
|
|
37
|
+
* cause is.
|
|
38
|
+
*/
|
|
39
|
+
export declare function synthesizeCapThoughts(events: CapEvents): string | undefined;
|
|
@@ -10,6 +10,14 @@ export declare const DEFAULT_MAX_INPUT_TOKENS = 128000;
|
|
|
10
10
|
export declare const CONTEXT_WINDOW_INPUT_RATIO = 0.9;
|
|
11
11
|
/** Compact once the transcript consumes this share of the usable input budget. */
|
|
12
12
|
export declare const COMPACTION_TRIGGER_RATIO = 0.9;
|
|
13
|
+
/**
|
|
14
|
+
* Upper bound on how far the provider's actual input count may scale the
|
|
15
|
+
* compaction budget down relative to the character-based estimate. Dense
|
|
16
|
+
* content realistically tokenizes ~2-3x denser than the 3-chars-per-token
|
|
17
|
+
* assumption; the cap stops a pathologically small estimate from collapsing
|
|
18
|
+
* the budget and compacting every turn.
|
|
19
|
+
*/
|
|
20
|
+
export declare const MAX_INPUT_UNDERESTIMATE_FACTOR = 4;
|
|
13
21
|
export declare const DEFAULT_TARGET_RATIO = 0.7;
|
|
14
22
|
export declare const DEFAULT_PRESERVE_RECENT_TOKENS = 20000;
|
|
15
23
|
/**
|
|
@@ -314,6 +322,29 @@ export declare function collectUserRequests(messages: readonly MessageWithMetada
|
|
|
314
322
|
export declare function findFirstUserMessageIndex(messages: MessageWithMetadata[]): number;
|
|
315
323
|
export declare function findLastTurnStartIndex(messages: MessageWithMetadata[]): number;
|
|
316
324
|
export declare function findLastAssistantIndex(messages: MessageWithMetadata[]): number;
|
|
325
|
+
/** What the agent runtime stamps on a turn whose content it replaced. */
|
|
326
|
+
export declare function isSpoiledTurn(message: MessageWithMetadata): boolean;
|
|
327
|
+
/**
|
|
328
|
+
* The transcript without a spoiled turn at its end.
|
|
329
|
+
*
|
|
330
|
+
* A turn that looped in its reasoning, or wrote a tool call nothing could
|
|
331
|
+
* read, has already had that content replaced by a note. If it is also the
|
|
332
|
+
* last thing in the transcript when compaction runs, it is the newest message
|
|
333
|
+
* and so the first one the recency tail keeps -- and what the model then reads
|
|
334
|
+
* straight after its replay is a turn in which it did nothing but fail.
|
|
335
|
+
* Measured before the content was replaced at all (pandorum, 2026-10-10): an
|
|
336
|
+
* unreadable call survived the compaction it caused and was written again,
|
|
337
|
+
* unchanged, four more times.
|
|
338
|
+
*
|
|
339
|
+
* So the tail is the messages before it, and it is not summarised either:
|
|
340
|
+
* nothing happened in it. Only when the turn called nothing. A looped turn
|
|
341
|
+
* that still ended on a tool call did something, the call and its result are
|
|
342
|
+
* the record of that, and they stay.
|
|
343
|
+
*
|
|
344
|
+
* The reminders the harness appended in answer to the turn go with it. They
|
|
345
|
+
* describe a turn that is no longer there.
|
|
346
|
+
*/
|
|
347
|
+
export declare function withoutTrailingSpoiledTurn(messages: MessageWithMetadata[]): MessageWithMetadata[];
|
|
317
348
|
export declare function findLatestSummaryIndex(messages: MessageWithMetadata[]): number;
|
|
318
349
|
/**
|
|
319
350
|
* The share of the material after a pinned prompt that a compaction folds when
|
|
@@ -524,7 +555,7 @@ export declare function buildSummaryRequest(options: {
|
|
|
524
555
|
* behaviour it is meant to flag. Hence the ban on specifics -- those are in the
|
|
525
556
|
* summary, and repeating them here spends the budget twice for one fact.
|
|
526
557
|
*/
|
|
527
|
-
export declare const DEFAULT_THINKING_COMPACTION_PROMPT = "You are writing
|
|
558
|
+
export declare const DEFAULT_THINKING_COMPACTION_PROMPT = "You are writing down what you now think about how this work has been going. It goes back into your own context after compaction, beside the replay of what happened, and you will read it as your own thought \u2014 so write it as the thought you are having right now, not as a report on a session.\n\nYou are reading your own reasoning from the work about to be discarded, together with what each stretch of it produced: which tool calls landed, which were refused, which were retried unchanged, and which turns ran long.\n\nWrite in the **first person, present tense**, in plain prose, in the same voice as the replay. You are not assessing something finished: you are in the middle of the work and saying how it is going. No headings, no bullet lists, no preamble, no sign-off.\n\nSay, in whatever order the thought runs:\n\n- what is working \u2014 the approaches that are producing progress, as approaches rather than as events;\n- what is not \u2014 the approaches that cost time and produce nothing, with the failure named: repeating an unchanged call, editing from a stale read, rewriting where narrowing would do, chasing a symptom;\n- where the time is going \u2014 the stretches that are expensive against what they achieve, including any turn where the reasoning runs long without converging;\n- what you do differently from here \u2014 concrete enough to act on, short enough to remember.\n\nSentences that open the way these do are the right shape: \"What is working is \u2026\", \"What keeps costing me is \u2026\", \"Most of my time is going into \u2026\", \"From here I \u2026\".\n\nRules:\n- No file names, line numbers, code, identifiers or values. Those are in the replay. This is about method.\n- No narration of the sequence of events. What you think of it, not what happened.\n- Leave out anything with nothing worth saying.\n- Short. A dozen sentences is a good one; a page is a failed one.";
|
|
528
559
|
export declare function buildThinkingSummaryRequest(options: {
|
|
529
560
|
previousThinkingSummary?: string;
|
|
530
561
|
reasoningText: string;
|
|
@@ -548,6 +579,35 @@ export declare function resolveSummarizerConfig(options: {
|
|
|
548
579
|
*/
|
|
549
580
|
outputTokenCap?: number;
|
|
550
581
|
}): ProviderConfig;
|
|
582
|
+
/** The retrospective and what the harness adds to it, as one text. */
|
|
583
|
+
export declare function composeRetrospective(thinkingSummary: string | undefined, harnessThoughts: string | undefined): string;
|
|
584
|
+
/** Marks the synthetic turn below, for the code that has to recognise it. */
|
|
585
|
+
export declare const COMPACTION_RETROSPECTIVE_KIND = "compaction_retrospective";
|
|
586
|
+
export declare function isRetrospectiveTurn(message: MessageWithMetadata): boolean;
|
|
587
|
+
/**
|
|
588
|
+
* The retrospective as a turn of the model's own, carried as its reasoning.
|
|
589
|
+
*
|
|
590
|
+
* As a text block in the summary it is something the model is told. The point
|
|
591
|
+
* of it is the opposite: that the model comes back from a compaction having
|
|
592
|
+
* already thought about how the work has been going -- including what the
|
|
593
|
+
* harness saw and it could not -- and acts on that as it acts on any thought
|
|
594
|
+
* of its own. That needs an assistant turn, because reasoning is only valid
|
|
595
|
+
* on one; a reasoning part on the summary itself, which has the user role,
|
|
596
|
+
* failed at the wire the first time it was tried.
|
|
597
|
+
*
|
|
598
|
+
* `pinnedReasoning` is what keeps it there. The replay policy sends back only
|
|
599
|
+
* the newest reasoning, and this turn stops being the newest on the very next
|
|
600
|
+
* request; the provider layer honours the pin where the server renders the
|
|
601
|
+
* field, and sends the same words as the turn's text where it does not, so
|
|
602
|
+
* the retrospective is never dropped and never sent as unsigned reasoning to
|
|
603
|
+
* an API that would refuse it.
|
|
604
|
+
*
|
|
605
|
+
* Only with a kept tail. A request cannot end on an assistant message, and a
|
|
606
|
+
* harness note appended after it would put a user turn between it and the
|
|
607
|
+
* model's next thought -- which, on the servers this is for, is exactly what
|
|
608
|
+
* removes earlier reasoning from the prompt.
|
|
609
|
+
*/
|
|
610
|
+
export declare function buildRetrospectiveTurn(text: string): MessageWithMetadata;
|
|
551
611
|
export declare function buildSummaryMessage(options: {
|
|
552
612
|
summary: string;
|
|
553
613
|
fileOps: FileOperationSummary;
|
|
@@ -556,6 +616,21 @@ export declare function buildSummaryMessage(options: {
|
|
|
556
616
|
generation?: number;
|
|
557
617
|
/** The retrospective, prepended as this message's own reasoning. */
|
|
558
618
|
thinkingSummary?: string;
|
|
619
|
+
/**
|
|
620
|
+
* What the harness adds to the retrospective in the model's own voice --
|
|
621
|
+
* see `synthesizeCapThoughts`.
|
|
622
|
+
*
|
|
623
|
+
* Shown with the retrospective and not stored as part of it: the next
|
|
624
|
+
* compaction hands `metadata.thinkingSummary` back as the previous
|
|
625
|
+
* retrospective, and a count of this generation's events fed into that
|
|
626
|
+
* would be restated as if it still described the work.
|
|
627
|
+
*/
|
|
628
|
+
harnessThoughts?: string;
|
|
629
|
+
/**
|
|
630
|
+
* The retrospective travels in a turn of its own, as that turn's reasoning
|
|
631
|
+
* (see {@link buildRetrospectiveTurn}), so it is left out of this message.
|
|
632
|
+
*/
|
|
633
|
+
retrospectiveAsTurn?: boolean;
|
|
559
634
|
/**
|
|
560
635
|
* The measured record of the tool calls being folded, appended after the
|
|
561
636
|
* summary — see {@link renderToolLedger}.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type PrepareTurnUsage } from "@cerebriline/shared";
|
|
1
|
+
import { type MessageWithMetadata, type PrepareTurnUsage } from "@cerebriline/shared";
|
|
2
2
|
import { type SessionCompactionState } from "../../session/models/session-compaction";
|
|
3
|
-
import type { CoreCompactionContext, CoreCompactionMode, CoreSessionConfig } from "../../types/config";
|
|
3
|
+
import type { CoreCompactionConfig, CoreCompactionContext, CoreCompactionMode, CoreSessionConfig } from "../../types/config";
|
|
4
4
|
import { type CompactionJournal } from "./compaction-journal";
|
|
5
5
|
export interface ContextPipelinePrepareTurnInput {
|
|
6
6
|
agentId: string;
|
|
@@ -35,6 +35,25 @@ export interface ContextPipelinePrepareTurnInput {
|
|
|
35
35
|
* (`compact_agents`). Runs as a manual compaction on this turn.
|
|
36
36
|
*/
|
|
37
37
|
compactionRequested?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Actual provider-reported input tokens for the previous request this run,
|
|
40
|
+
* used as a floor on the char-based estimate so dense content still triggers
|
|
41
|
+
* compaction. See AgentPrepareTurnContext.previousRequestInputTokens.
|
|
42
|
+
*/
|
|
43
|
+
previousRequestInputTokens?: number;
|
|
44
|
+
/**
|
|
45
|
+
* The transcript as the session holds it, when a stage ahead of this one
|
|
46
|
+
* rewrote a message in `messages`.
|
|
47
|
+
*
|
|
48
|
+
* A saved compaction is matched to the transcript by a hash of everything
|
|
49
|
+
* it replaced. Hashed over a rewritten transcript, it matches only while
|
|
50
|
+
* the same rewrite is applied -- and the capped-thinking condenser rewrites
|
|
51
|
+
* the newest turn that reasoned, which is a different turn one request
|
|
52
|
+
* later. Measured on pandorum (2026-10-11): a compaction to 39,341 tokens,
|
|
53
|
+
* and the very next request sent all 83,853 again and compacted a second
|
|
54
|
+
* time. The hash is taken over this, which no stage rewrites.
|
|
55
|
+
*/
|
|
56
|
+
sourceMessages?: CoreCompactionContext["messages"];
|
|
38
57
|
emitStatusNotice?: (message: string, metadata?: Record<string, unknown>) => void;
|
|
39
58
|
/**
|
|
40
59
|
* Count what this preparation spent on the model. Every call of a
|
|
@@ -67,6 +86,8 @@ export interface ContextCompactionPrepareTurnOptions {
|
|
|
67
86
|
* must never close the lead.
|
|
68
87
|
*/
|
|
69
88
|
sideCallOf?: string;
|
|
89
|
+
/** Overrides layered over `config.compaction`. */
|
|
90
|
+
compaction?: Partial<CoreCompactionConfig>;
|
|
70
91
|
}
|
|
71
92
|
/**
|
|
72
93
|
* The share of the *content* a compaction aims to leave behind.
|
|
@@ -86,6 +107,33 @@ export interface ContextCompactionPrepareTurnOptions {
|
|
|
86
107
|
* has an answer for any window.
|
|
87
108
|
*/
|
|
88
109
|
export declare const COMPACTION_TARGET_CONTENT_SHARE = 0.25;
|
|
110
|
+
/**
|
|
111
|
+
* The most of the free content a recovery compaction may leave in place.
|
|
112
|
+
*
|
|
113
|
+
* A recovery runs because a reply did not fit, so what it leaves has to have
|
|
114
|
+
* room for one. Its target used to be capped only by the trigger, which is
|
|
115
|
+
* nine tenths of the window: measured (harness run 0428, 2026-10-11, window
|
|
116
|
+
* 85,106), each recovery left 53,345 tokens in the request, the retried turn
|
|
117
|
+
* wrote 22,361 and read a 6,000-token result, and the turn after that was cut
|
|
118
|
+
* off again -- three times running. Half the content leaves that turn its
|
|
119
|
+
* room; an ordinary compaction aims at a quarter.
|
|
120
|
+
*/
|
|
121
|
+
export declare const OVERFLOW_RECOVERY_CONTENT_SHARE = 0.5;
|
|
122
|
+
/**
|
|
123
|
+
* A summarised recovery transcript, cut down to the recovery target.
|
|
124
|
+
*
|
|
125
|
+
* The summarising attempt keeps a tail of recent turns after its summary, and
|
|
126
|
+
* with a tail of large turns it comes back over the target. It used to be
|
|
127
|
+
* thrown away for that and basic compaction used in its place -- five model
|
|
128
|
+
* calls and about 200 seconds, three times in one run, for a transcript that
|
|
129
|
+
* had the work in it and none of the reasons. The summary is the part worth
|
|
130
|
+
* having, so the tail gives way instead: the leading compaction messages
|
|
131
|
+
* stay, and the tail keeps its newest turns for as long as they fit.
|
|
132
|
+
*
|
|
133
|
+
* `undefined` when there is no summary at the head or it does not fit by
|
|
134
|
+
* itself: then basic compaction is no worse and needs nothing checked.
|
|
135
|
+
*/
|
|
136
|
+
export declare function trimSummarisedTailToTarget(messages: readonly MessageWithMetadata[] | undefined, targetTokens: number, estimate: (message: MessageWithMetadata) => number): MessageWithMetadata[] | undefined;
|
|
89
137
|
/**
|
|
90
138
|
* How many tokens of transcript a compaction should leave.
|
|
91
139
|
*
|
|
@@ -152,7 +200,27 @@ export declare function resolveMessageTargetOnTriggerScale(input: {
|
|
|
152
200
|
export declare function scaleEstimateToObserved(estimate: number, estimateOfObserved: number, observed: number | undefined): number;
|
|
153
201
|
/** Test seam: the latch is process-wide, so a suite has to be able to clear it. */
|
|
154
202
|
export declare function resetStarvedOutputCapLatch(): void;
|
|
155
|
-
export declare function createContextCompactionPrepareTurn(config: Pick<CoreSessionConfig, "providerConfig" | "providerId" | "modelId" | "compaction" | "logger" | "telemetry" | "sessionId"> & Partial<Pick<CoreSessionConfig, "thinking" | "reasoningEffort" | "thinkingBudgetTokens" | "temperature">>, options?: ContextCompactionPrepareTurnOptions): ((context: ContextPipelinePrepareTurnInput) => Promise<ContextPipelinePrepareTurnResult | undefined>) | undefined;
|
|
203
|
+
export declare function createContextCompactionPrepareTurn(config: Pick<CoreSessionConfig, "providerConfig" | "providerId" | "modelId" | "apiKey" | "baseUrl" | "headers" | "compaction" | "logger" | "telemetry" | "sessionId"> & Partial<Pick<CoreSessionConfig, "thinking" | "reasoningEffort" | "thinkingBudgetTokens" | "temperature">>, options?: ContextCompactionPrepareTurnOptions): ((context: ContextPipelinePrepareTurnInput) => Promise<ContextPipelinePrepareTurnResult | undefined>) | undefined;
|
|
204
|
+
/**
|
|
205
|
+
* Compaction policy for resuming a session imported from another coding agent.
|
|
206
|
+
* The imported transcript keeps that agent's tool names and input schemas
|
|
207
|
+
* verbatim, which a model continuing it may try to call, so the first turn
|
|
208
|
+
* folds the whole foreign history into a summary before the model request
|
|
209
|
+
* (manual mode, agentic strategy, nothing preserved but the new prompt).
|
|
210
|
+
* Runs regardless of the session's auto-compaction setting, tags its status
|
|
211
|
+
* notices with `importedFrom` so clients can label the wait, and on failure
|
|
212
|
+
* falls back to the raw transcript. It makes one attempt per session start
|
|
213
|
+
* (an aborted attempt does not count) and stands down once the working
|
|
214
|
+
* context already opens with a compaction summary, which is how a resumed
|
|
215
|
+
* sidecar presents; every other turn defers to `next`, the session's normal
|
|
216
|
+
* compaction (if any).
|
|
217
|
+
*/
|
|
218
|
+
export declare function createImportedHistoryCompactionPrepareTurn(input: {
|
|
219
|
+
config: Parameters<typeof createContextCompactionPrepareTurn>[0];
|
|
220
|
+
/** Source tool id from the session's `importedFrom` metadata. */
|
|
221
|
+
importedFrom: string;
|
|
222
|
+
next?: ContextPipelinePrepareTurn;
|
|
223
|
+
}): ContextPipelinePrepareTurn;
|
|
156
224
|
export declare function createCompactionStateAwarePrepareTurn(input: {
|
|
157
225
|
compact?: ContextPipelinePrepareTurn;
|
|
158
226
|
getState?: () => SessionCompactionState | undefined;
|
|
@@ -164,4 +232,8 @@ export declare function createCompactionStateAwarePrepareTurn(input: {
|
|
|
164
232
|
* spuriously reject the write.
|
|
165
233
|
*/
|
|
166
234
|
saveState?: (state: SessionCompactionState, sourceMessages: CoreCompactionContext["messages"]) => void | Promise<void>;
|
|
235
|
+
/** Told when a saved compaction no longer matches the transcript. */
|
|
236
|
+
logger?: {
|
|
237
|
+
log?: (message: string) => void;
|
|
238
|
+
};
|
|
167
239
|
}): ContextPipelinePrepareTurn;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { FetchLike } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
2
2
|
import type { McpServerClientFactory } from "./types";
|
|
3
|
-
export declare const DEFAULT_MCP_CONNECT_TIMEOUT_MS =
|
|
3
|
+
export declare const DEFAULT_MCP_CONNECT_TIMEOUT_MS = 10000;
|
|
4
4
|
export declare const DEFAULT_HTTP_MCP_CONNECT_TIMEOUT_MS = 10000;
|
|
5
5
|
export interface DefaultMcpServerClientFactoryOptions {
|
|
6
6
|
settingsPath?: string;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Factory functions for creating the default tools.
|
|
5
5
|
*/
|
|
6
|
-
import { type AgentTool
|
|
6
|
+
import { type AgentTool } from "@cerebriline/shared";
|
|
7
7
|
import { type QaCredential } from "./qa-credentials";
|
|
8
8
|
import { type ApplyPatchInput, type AskQuestionInput, type AwkToolInput, type EditFileInput, type ExtractDocumentInput, type FetchWebContentInput, type GrepToolInput, type ReadFileRequest, type ReadFilesInput, type SearchCodebaseInput, type SedToolInput, type SkillsInput, type SubmitInput } from "./schemas";
|
|
9
9
|
import type { ApplyPatchExecutor, AskQuestionExecutor, AwkExecutor, CreateDefaultToolsOptions, DefaultToolsConfig, EditorExecutor, ExtractDocumentExecutor, FileReadExecutor, GrepExecutor, SearchExecutor, SedExecutor, SemanticSearchExecutor, ShellExecutor, SkillsExecutorWithMetadata, ToolOperationResult, VerifySubmitExecutor, WebFetchExecutor } from "./types";
|
|
@@ -44,11 +44,11 @@ export declare function createReadFilesTool(executor: FileReadExecutor, config?:
|
|
|
44
44
|
export declare function createSearchTool(executor: SearchExecutor, config?: Pick<DefaultToolsConfig, "cwd" | "searchTimeoutMs">, semantic?: SemanticSearchExecutor["search"]): AgentTool<SearchCodebaseInput, ToolOperationResult[]>;
|
|
45
45
|
/**
|
|
46
46
|
* Build the run_commands tool description for the shell that will actually
|
|
47
|
-
* execute the commands.
|
|
48
|
-
*
|
|
49
|
-
*
|
|
47
|
+
* execute the commands. Derive the edition and wrapper guidance from the
|
|
48
|
+
* same executable, without probing a version or adding volatile prompt text.
|
|
49
|
+
* isWindows describes the host, not the shell's edition.
|
|
50
50
|
*/
|
|
51
|
-
export declare function buildRunCommandsDescription(
|
|
51
|
+
export declare function buildRunCommandsDescription(shell: string, isWindows: boolean): string;
|
|
52
52
|
/**
|
|
53
53
|
* Create the run_commands shell tool for the current platform.
|
|
54
54
|
*
|
|
@@ -28,6 +28,32 @@ export declare class CommandExitError extends Error {
|
|
|
28
28
|
readonly output: string;
|
|
29
29
|
constructor(exitCode: number, output: string);
|
|
30
30
|
}
|
|
31
|
+
/** The process terminated without a numeric exit code, usually by signal. */
|
|
32
|
+
export declare class CommandTerminationError extends Error {
|
|
33
|
+
readonly signal: NodeJS.Signals | null;
|
|
34
|
+
readonly output: string;
|
|
35
|
+
constructor(signal: NodeJS.Signals | null, output: string);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The shell process could not be started, so the command never ran and there
|
|
39
|
+
* is no exit code. `code` carries the operating system error libuv reported —
|
|
40
|
+
* `ENOENT`, `EACCES`, `EFTYPE` for a file that is not a valid executable — so
|
|
41
|
+
* a host can count "the shell is missing" separately from "the command
|
|
42
|
+
* failed" without parsing the message.
|
|
43
|
+
*
|
|
44
|
+
* `ENOENT` alone is ambiguous: spawn reports it both when the executable is
|
|
45
|
+
* not found and when the working directory no longer exists, with the same
|
|
46
|
+
* message. `missing` settles it by checking the directory at failure time, so
|
|
47
|
+
* "shell not on PATH" and "workspace folder gone" stay separately countable.
|
|
48
|
+
*/
|
|
49
|
+
export declare class CommandSpawnError extends Error {
|
|
50
|
+
readonly code: string | undefined;
|
|
51
|
+
/** For `ENOENT`, which path was absent. Undefined for every other code. */
|
|
52
|
+
readonly missing: "executable" | "cwd" | undefined;
|
|
53
|
+
constructor(cause: Error, options?: {
|
|
54
|
+
cwd?: string;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
31
57
|
export interface ShellExecutorOptions {
|
|
32
58
|
/**
|
|
33
59
|
* Shell to use for execution
|
|
@@ -21,7 +21,7 @@ import { type WebFetchExecutorOptions } from "./web-fetch";
|
|
|
21
21
|
export { type ApplyPatchExecutorOptions, computePatchChanges, createApplyPatchExecutor, type PatchFileChange, } from "./apply-patch";
|
|
22
22
|
export { PATCH_MARKERS, PatchActionType } from "./apply-patch-parser";
|
|
23
23
|
export { type AwkExecutorOptions, createAwkExecutor } from "./awk";
|
|
24
|
-
export { CommandExitError, createShellExecutor, type ShellExecutorOptions, } from "./bash";
|
|
24
|
+
export { CommandExitError, CommandSpawnError, CommandTerminationError, createShellExecutor, type ShellExecutorOptions, } from "./bash";
|
|
25
25
|
export { DOCUMENT_EXTENSIONS } from "./document/formats";
|
|
26
26
|
export { createDocumentExtractExecutor, DEFAULT_EXTRACTION_DIR, type DocumentExtractExecutorOptions, } from "./document-extract";
|
|
27
27
|
export { createEditorExecutor, type EditorExecutorOptions } from "./editor";
|
|
@@ -7,7 +7,7 @@ export { validateWithZod, zodToJsonSchema } from "@cerebriline/shared";
|
|
|
7
7
|
export { createPlanModeCommandGuardExtension, PLAN_MODE_COMMAND_GUARD_EXTENSION_NAME, type PlanModeCommandGuardOptions, } from "./command-guard-extension";
|
|
8
8
|
export { ALL_DEFAULT_TOOL_NAMES, DefaultToolNames } from "./constants";
|
|
9
9
|
export { createApplyPatchTool, createAskQuestionTool, createAwkTool, createDefaultTools, createEditorTool, createExtractDocumentTool, createGrepTool, createReadFilesTool, createSearchTool, createSedTool, createShellTool, createSkillsTool, createSubmitAndExitTool, createWebFetchTool, } from "./definitions";
|
|
10
|
-
export { type ApplyPatchExecutorOptions, type AwkExecutorOptions, CommandExitError, computePatchChanges, createApplyPatchExecutor, createAwkExecutor, createDefaultExecutors, createDefaultShellExecutor, createDocumentExtractExecutor, createEditorExecutor, createFileReadExecutor, createGrepExecutor, createReadReceipts, createSearchExecutor, createSedExecutor, createShellExecutor, createWebFetchExecutor, DEFAULT_EXTRACTION_DIR, type DefaultExecutorsOptions, DOCUMENT_EXTENSIONS, type DocumentExtractExecutorOptions, type EditorExecutorOptions, type FileReadExecutorOptions, type GrepExecutorOptions, PATCH_MARKERS, PatchActionType, type PatchFileChange, type ReadReceipts, RunCommandExecutionController, type RunningCommandRegistration, type SearchExecutorOptions, type SedExecutorOptions, type ShellExecutorOptions, type WebFetchExecutorOptions, } from "./executors/index";
|
|
10
|
+
export { type ApplyPatchExecutorOptions, type AwkExecutorOptions, CommandExitError, CommandSpawnError, CommandTerminationError, computePatchChanges, createApplyPatchExecutor, createAwkExecutor, createDefaultExecutors, createDefaultShellExecutor, createDocumentExtractExecutor, createEditorExecutor, createFileReadExecutor, createGrepExecutor, createReadReceipts, createSearchExecutor, createSedExecutor, createShellExecutor, createWebFetchExecutor, DEFAULT_EXTRACTION_DIR, type DefaultExecutorsOptions, DOCUMENT_EXTENSIONS, type DocumentExtractExecutorOptions, type EditorExecutorOptions, type FileReadExecutorOptions, type GrepExecutorOptions, PATCH_MARKERS, PatchActionType, type PatchFileChange, type ReadReceipts, RunCommandExecutionController, type RunningCommandRegistration, type SearchExecutorOptions, type SedExecutorOptions, type ShellExecutorOptions, type WebFetchExecutorOptions, } from "./executors/index";
|
|
11
11
|
export { MAX_COMMAND_OUTPUT_CHARS, MAX_READ_REFUSAL_CHARS, truncateCommandOutput, } from "./executors/output-limits";
|
|
12
12
|
export { DEFAULT_MODEL_TOOL_ROUTING_RULES, resolveToolRoutingConfig, type ToolRoutingRule, } from "./model-tool-routing";
|
|
13
13
|
export { createDefaultToolsWithPreset, createToolPoliciesWithPreset, resolveToolPresetName, type ToolPolicyPresetName, type ToolPresetName, ToolPresets, } from "./presets";
|
|
@@ -169,10 +169,28 @@ export interface TaskProgressTrackerOptions {
|
|
|
169
169
|
* carried a checklist — a model that has stopped updating the list is exactly
|
|
170
170
|
* the one that needs to see it again.
|
|
171
171
|
*/
|
|
172
|
+
/**
|
|
173
|
+
* The nudge for a file changed outside the checklist.
|
|
174
|
+
*
|
|
175
|
+
* Two situations, one rule: a call that changes a file is work on a step, so
|
|
176
|
+
* if no step is open the list is wrong. Either there is no list at all, or the
|
|
177
|
+
* list says everything is done and the work has carried on. Measured over 22
|
|
178
|
+
* v9-agentic sessions (pandorum, 2026-10-10): 12 of the 15 that edited never
|
|
179
|
+
* sent a list; one sent a single item at its 5th call, ticked it at its 6th
|
|
180
|
+
* and made 7 of its 10 edits afterwards; another re-sent the same finished
|
|
181
|
+
* one-item list 16 times across five more edits.
|
|
182
|
+
*
|
|
183
|
+
* Reads never trigger it. A run that only looks may simply be finished.
|
|
184
|
+
*/
|
|
185
|
+
export declare function buildUntrackedEditNudge(kind: "missing" | "finished", path: string | undefined): string;
|
|
172
186
|
export declare class TaskProgressTracker {
|
|
173
187
|
private state;
|
|
174
188
|
private callsSinceReminder;
|
|
175
189
|
private writesSinceReminder;
|
|
190
|
+
/** Edits made since a list with an open step was last sent. */
|
|
191
|
+
private untrackedEdits;
|
|
192
|
+
/** A reminder waiting for the turn's tool calls to finish. */
|
|
193
|
+
private pending;
|
|
176
194
|
private readonly reminderInterval;
|
|
177
195
|
private readonly writeInterval;
|
|
178
196
|
private readonly onUpdate;
|
|
@@ -202,6 +220,25 @@ export declare class TaskProgressTracker {
|
|
|
202
220
|
* demonstrated it has the list, and echoing it straight back is pure cost.
|
|
203
221
|
*/
|
|
204
222
|
recordToolCall(input: unknown, toolName?: string): string | undefined;
|
|
223
|
+
private hasItems;
|
|
224
|
+
private isFinished;
|
|
225
|
+
/**
|
|
226
|
+
* Count an edit made with no step open, and queue the nudge when one is due.
|
|
227
|
+
*
|
|
228
|
+
* The first such edit, then every `writeInterval` after it: said once it
|
|
229
|
+
* can be missed, said on every edit it is noise the model learns to skip.
|
|
230
|
+
*/
|
|
231
|
+
private noteUntrackedEdit;
|
|
232
|
+
/**
|
|
233
|
+
* Hold a reminder for delivery after the turn's tool calls.
|
|
234
|
+
*
|
|
235
|
+
* For the reminders that could not be appended to a result because the
|
|
236
|
+
* result is not text. An untracked-edit nudge already waiting is kept: it
|
|
237
|
+
* is the more specific of the two.
|
|
238
|
+
*/
|
|
239
|
+
queueReminder(reminder: string): void;
|
|
240
|
+
/** The reminder waiting to be delivered, cleared by the read. */
|
|
241
|
+
takePendingReminder(): string | undefined;
|
|
205
242
|
}
|
|
206
243
|
/**
|
|
207
244
|
* Wrap a tool so its calls feed the tracker and its results carry reminders.
|
|
@@ -11,6 +11,7 @@ export { type AgentProfileConnection, type AgentProviderConnection, buildConfigu
|
|
|
11
11
|
export { type ConfiguredAgentDelegationResult, type ConfiguredAgentSummary, type DelegateToConfiguredAgentInput, delegateToConfiguredAgent, findConfiguredAgent, listConfiguredAgentSummaries, renderDelegationForTranscript, UnknownConfiguredAgentError, } from "./delegate-to-agent";
|
|
12
12
|
export { type EngineEviction, engineEvictionCount, engineEvictions, recordEngineEviction, resetEngineEvictions, } from "./engine-evictions";
|
|
13
13
|
export { isNodeUnreachable } from "./node-reachability";
|
|
14
|
+
export { isDurableTeamEvent, shouldFlushTeamEventImmediately, TEAM_RUN_RESULT_TEXT_LIMIT, type TeamRunResultRecord, toPersistableTeamEvent, toTeamRunResultRecord, } from "./persistence-policy";
|
|
14
15
|
export { buildTeamProgressSummary, toTeamProgressLifecycleEvent, } from "./projections";
|
|
15
16
|
export * from "./runtime";
|
|
16
17
|
export { isSessionAllocationFull, retryWhileSessionFull, } from "./session-window-retry";
|
|
@@ -6,6 +6,25 @@
|
|
|
6
6
|
import { type AgentConfig, type AgentEvent, type AgentResult, type AppendMissionLogInput, type AttachTeamOutcomeFragmentInput, type CreateTeamOutcomeInput, type CreateTeamTaskInput, type MissionLogEntry, type ReviewTeamOutcomeFragmentInput, type RouteToTeammateOptions, type TeamAgentSampling, type TeamMailboxMessage, type TeamMemberSnapshot, TeamMessageType, type TeammateLifecycleSpec, type TeamOutcome, type TeamOutcomeFragment, type TeamRunRecord, type TeamRunStatus, type TeamRuntimeSnapshot, type TeamRuntimeState, type TeamTask, type TeamTaskListItem, type TeamTaskStatus } from "@cerebriline/shared";
|
|
7
7
|
import { SessionRuntime } from "../../../runtime/orchestration/session-runtime-orchestrator";
|
|
8
8
|
import { type HandedRevision } from "./delegated-sandboxes";
|
|
9
|
+
/**
|
|
10
|
+
* Incremental change set produced by `AgentTeamsRuntime.drainStateDelta()`.
|
|
11
|
+
* Only entities mutated since the previous drain are included, so the cost of
|
|
12
|
+
* persisting it is proportional to what changed, not to team history.
|
|
13
|
+
*/
|
|
14
|
+
export interface TeamRuntimeStateDelta {
|
|
15
|
+
teamId: string;
|
|
16
|
+
teamName: string;
|
|
17
|
+
/** When true, the store must drop all persisted entities before applying. */
|
|
18
|
+
reset: boolean;
|
|
19
|
+
/** Members are few and cheap; always included in full. */
|
|
20
|
+
members: TeamMemberSnapshot[];
|
|
21
|
+
tasks: TeamTask[];
|
|
22
|
+
mailbox: TeamMailboxMessage[];
|
|
23
|
+
missionLog: MissionLogEntry[];
|
|
24
|
+
runs: TeamRunRecord[];
|
|
25
|
+
outcomes: TeamOutcome[];
|
|
26
|
+
outcomeFragments: TeamOutcomeFragment[];
|
|
27
|
+
}
|
|
9
28
|
export { type AppendMissionLogInput, type AttachTeamOutcomeFragmentInput, type CreateTeamOutcomeInput, type CreateTeamTaskInput, type MissionLogEntry, type MissionLogKind, type ReviewTeamOutcomeFragmentInput, type RouteToTeammateOptions, type TeamMailboxMessage, type TeamMemberSnapshot, TeamMessageType, type TeammateLifecycleSpec, type TeamOutcome, type TeamOutcomeFragment, type TeamOutcomeFragmentStatus, type TeamOutcomeStatus, type TeamRunRecord, type TeamRunStatus, type TeamRuntimeSnapshot, type TeamRuntimeState, type TeamTask, type TeamTaskListItem, type TeamTaskStatus, } from "@cerebriline/shared";
|
|
10
29
|
export interface TeamMemberConfig extends AgentConfig {
|
|
11
30
|
role?: string;
|
|
@@ -123,6 +142,11 @@ export interface AgentTeamsRuntimeOptions {
|
|
|
123
142
|
missionLogIntervalMs?: number;
|
|
124
143
|
maxConcurrentRuns?: number;
|
|
125
144
|
onTeamEvent?: (event: TeamEvent) => void;
|
|
145
|
+
/**
|
|
146
|
+
* Called when persisted state changes without a team event (mailbox read
|
|
147
|
+
* receipts, cleanup), so a persistence writer can schedule a flush.
|
|
148
|
+
*/
|
|
149
|
+
onStateDirty?: () => void;
|
|
126
150
|
/**
|
|
127
151
|
* The teammates' private workspaces, when the host sandboxes them. A
|
|
128
152
|
* teammate's toolset opens its workspace when it is spawned; the runtime
|
|
@@ -199,6 +223,7 @@ export declare class AgentTeamsRuntime {
|
|
|
199
223
|
private readonly teamName;
|
|
200
224
|
private readonly sessionId?;
|
|
201
225
|
private readonly onTeamEvent?;
|
|
226
|
+
private readonly onStateDirty?;
|
|
202
227
|
private readonly members;
|
|
203
228
|
private readonly tasks;
|
|
204
229
|
private readonly missionLog;
|
|
@@ -211,6 +236,7 @@ export declare class AgentTeamsRuntime {
|
|
|
211
236
|
private outcomeCounter;
|
|
212
237
|
private outcomeFragmentCounter;
|
|
213
238
|
private readonly runs;
|
|
239
|
+
private dirty;
|
|
214
240
|
private readonly runQueue;
|
|
215
241
|
private queuedRunDispatchTimer;
|
|
216
242
|
private readonly outcomes;
|
|
@@ -360,5 +386,27 @@ export declare class AgentTeamsRuntime {
|
|
|
360
386
|
private formatProgressErrorActivity;
|
|
361
387
|
private recordProgressStep;
|
|
362
388
|
private buildMailboxNotification;
|
|
389
|
+
/**
|
|
390
|
+
* Record which persisted entity an event mutated. Every durable state
|
|
391
|
+
* change flows through `emitEvent`, so this is the single point that keeps
|
|
392
|
+
* the dirty set in sync with the in-memory maps.
|
|
393
|
+
*/
|
|
394
|
+
private markDirtyFromEvent;
|
|
395
|
+
/** True when there are unpersisted changes. */
|
|
396
|
+
hasPendingStateDelta(): boolean;
|
|
397
|
+
/**
|
|
398
|
+
* Return entities mutated since the last drain and clear the dirty set.
|
|
399
|
+
* Ids whose entity no longer exists are skipped (a `reset` covers removal).
|
|
400
|
+
*/
|
|
401
|
+
drainStateDelta(): TeamRuntimeStateDelta;
|
|
402
|
+
/**
|
|
403
|
+
* Put a drained delta back so a failed write is retried by the next flush.
|
|
404
|
+
* Entities are re-read at drain time, so only ids and the reset flag matter.
|
|
405
|
+
*/
|
|
406
|
+
requeueStateDelta(delta: TeamRuntimeStateDelta): void;
|
|
407
|
+
private notifyStateDirty;
|
|
408
|
+
/** Mark the whole state dirty (used after hydrate/cleanup or a migration). */
|
|
409
|
+
markAllStateDirty(reset?: boolean): void;
|
|
410
|
+
private exportMembers;
|
|
363
411
|
private emitEvent;
|
|
364
412
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type AgentResult, type LegacyAgentUsage } from "@cerebriline/shared";
|
|
2
|
+
import type { TeamEvent } from "./multi-agent";
|
|
3
|
+
/**
|
|
4
|
+
* Persistence policy for team events.
|
|
5
|
+
*
|
|
6
|
+
* Team events fall into two classes:
|
|
7
|
+
* - **durable**: they mutate team state that must survive a restart
|
|
8
|
+
* (tasks, mailbox, mission log, run lifecycle, outcomes, membership).
|
|
9
|
+
* - **telemetry**: high-frequency liveness signals (streamed agent chunks,
|
|
10
|
+
* run heartbeats/activity). These are forwarded to live UIs only and are
|
|
11
|
+
* never written to disk.
|
|
12
|
+
*
|
|
13
|
+
* The switch is exhaustive so adding a new `TeamMessageType` fails to compile
|
|
14
|
+
* until it is classified here.
|
|
15
|
+
*/
|
|
16
|
+
export declare function isDurableTeamEvent(event: TeamEvent): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Durable events that should be flushed to storage immediately instead of
|
|
19
|
+
* waiting for the batch window: terminal run states and membership changes,
|
|
20
|
+
* where losing the write on a crash would leave recovery in a wrong state.
|
|
21
|
+
*/
|
|
22
|
+
export declare function shouldFlushTeamEventImmediately(event: TeamEvent): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Compact form of an `AgentResult` kept on team run records. Contains exactly
|
|
25
|
+
* the fields consumed by run summaries; the full transcript (messages, tool
|
|
26
|
+
* calls) already lives in the teammate's session storage.
|
|
27
|
+
*/
|
|
28
|
+
export interface TeamRunResultRecord {
|
|
29
|
+
text: string;
|
|
30
|
+
iterations: number;
|
|
31
|
+
finishReason: AgentResult["finishReason"];
|
|
32
|
+
durationMs: number;
|
|
33
|
+
usage: LegacyAgentUsage;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Upstream's upper bound for final text kept on a run record (4,000 there).
|
|
37
|
+
*
|
|
38
|
+
* Not applied on this fork: the run record is where a teammate's answer comes
|
|
39
|
+
* from when the lead awaits it, and a long one is filed whole as a report the
|
|
40
|
+
* lead reads with `read_agent_report`. Cut here, the report ended at
|
|
41
|
+
* character 4,000 with "..." and said it was "the end of the report". The
|
|
42
|
+
* record still drops the transcript and the tool calls, which is where the
|
|
43
|
+
* size was.
|
|
44
|
+
*/
|
|
45
|
+
export declare const TEAM_RUN_RESULT_TEXT_LIMIT: number;
|
|
46
|
+
/**
|
|
47
|
+
* Reduce a full (or legacy persisted) agent result to a `TeamRunResultRecord`.
|
|
48
|
+
* Accepts `unknown` because persisted rows written by older versions may hold
|
|
49
|
+
* a full `AgentResult` with dates serialized as strings.
|
|
50
|
+
*/
|
|
51
|
+
export declare function toTeamRunResultRecord(result: unknown): TeamRunResultRecord | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Strip heavy payloads (full transcripts, tool calls) from an event before it
|
|
54
|
+
* is appended to the durable event log.
|
|
55
|
+
*/
|
|
56
|
+
export declare function toPersistableTeamEvent(event: TeamEvent): unknown;
|