indusagi-coding-agent 0.2.5 → 0.2.9
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/CHANGELOG.md +9 -0
- package/README.md +9 -5
- package/dist/entry.js +14267 -24282
- package/dist/guardrails.js +924 -7867
- package/dist/index.js +13706 -23775
- package/package.json +3 -2
- package/src/_decls/entry.ts +18 -0
- package/src/_decls/guardrails.ts +35 -0
- package/src/_decls/index.ts +26 -0
- package/src/addons/contract.ts +236 -0
- package/src/addons/dispatch/event-dispatcher.ts +164 -0
- package/src/addons/dispatch/index.ts +25 -0
- package/src/addons/dispatch/tool-interceptor.ts +208 -0
- package/src/addons/host.ts +225 -0
- package/src/addons/index.ts +112 -0
- package/src/addons/manifest.ts +158 -0
- package/src/addons/sandbox.ts +170 -0
- package/src/addons/surface.ts +78 -0
- package/src/boot/auth-vault.ts +195 -0
- package/src/boot/boot.ts +138 -0
- package/src/boot/contract.ts +238 -0
- package/src/boot/heap.ts +59 -0
- package/src/boot/index.ts +28 -0
- package/src/boot/invocation.ts +93 -0
- package/src/boot/runners/addon-wiring.ts +153 -0
- package/src/boot/runners/checkpoint.ts +169 -0
- package/src/boot/runners/delegate-runner.ts +294 -0
- package/src/boot/runners/index.ts +13 -0
- package/src/boot/runners/link-runner.ts +45 -0
- package/src/boot/runners/memdir.ts +168 -0
- package/src/boot/runners/oneshot-runner.ts +58 -0
- package/src/boot/runners/read-state.ts +90 -0
- package/src/boot/runners/registry.ts +42 -0
- package/src/boot/runners/repl-runner.ts +143 -0
- package/src/boot/runners/server-mode.ts +121 -0
- package/src/boot/runners/session.ts +641 -0
- package/src/boot/server-token.ts +148 -0
- package/src/boot/stages.ts +167 -0
- package/src/boot/upgrade/apply.ts +94 -0
- package/src/boot/upgrade/index.ts +13 -0
- package/src/boot/upgrade/upgrades.ts +289 -0
- package/src/briefing/compose.ts +150 -0
- package/src/briefing/context-docs.ts +19 -0
- package/src/briefing/contract.ts +717 -0
- package/src/briefing/index.ts +31 -0
- package/src/briefing/macros.ts +97 -0
- package/src/briefing/skills.ts +47 -0
- package/src/capability-deck/bridge-ledger/index.ts +27 -0
- package/src/capability-deck/bridge-ledger/key.ts +67 -0
- package/src/capability-deck/bridge-ledger/ledger.ts +131 -0
- package/src/capability-deck/bridge-ledger/network.ts +117 -0
- package/src/capability-deck/builtin-bridge.ts +312 -0
- package/src/capability-deck/cards/bg-process-card.ts +335 -0
- package/src/capability-deck/cards/index.ts +115 -0
- package/src/capability-deck/cards/memory-card.ts +146 -0
- package/src/capability-deck/cards/plan-file.ts +97 -0
- package/src/capability-deck/cards/plan-tools.ts +185 -0
- package/src/capability-deck/cards/saas-card.ts +183 -0
- package/src/capability-deck/cards/task-card.ts +207 -0
- package/src/capability-deck/cards/todo-card.ts +168 -0
- package/src/capability-deck/cards/workflow-card.ts +247 -0
- package/src/capability-deck/contract.ts +388 -0
- package/src/capability-deck/index.ts +48 -0
- package/src/capability-deck/manifest.ts +109 -0
- package/src/capability-deck/provision.ts +169 -0
- package/src/channels/contract.ts +191 -0
- package/src/channels/framer.ts +50 -0
- package/src/channels/index.ts +101 -0
- package/src/channels/link/dialog.ts +129 -0
- package/src/channels/link/driver.ts +190 -0
- package/src/channels/link/index.ts +34 -0
- package/src/channels/link/server.ts +134 -0
- package/src/channels/oneshot.ts +90 -0
- package/src/channels/ops.ts +65 -0
- package/src/channels/session-ops.ts +81 -0
- package/src/conductor/bash-guard.ts +599 -0
- package/src/conductor/catalog/catalog.ts +116 -0
- package/src/conductor/catalog/index.ts +8 -0
- package/src/conductor/catalog/matcher.ts +134 -0
- package/src/conductor/conductor.ts +234 -0
- package/src/conductor/contract.ts +842 -0
- package/src/conductor/diagnostics.ts +227 -0
- package/src/conductor/index.ts +33 -0
- package/src/conductor/permissions.ts +588 -0
- package/src/conductor/quota-error.ts +49 -0
- package/src/conductor/signal-hub/hub.ts +46 -0
- package/src/conductor/signal-hub/index.ts +2 -0
- package/src/conductor/signal-hub/translate.test.ts +81 -0
- package/src/conductor/signal-hub/translate.ts +74 -0
- package/src/conductor/skill-parse/index.ts +2 -0
- package/src/conductor/skill-parse/parse.ts +108 -0
- package/src/conductor/transcript-store/index.ts +22 -0
- package/src/conductor/transcript-store/serialize.ts +116 -0
- package/src/conductor/transcript-store/store.ts +205 -0
- package/src/console/auth-status.ts +56 -0
- package/src/console/components/AgentsView.ts +165 -0
- package/src/console/components/BackgroundAgents.ts +155 -0
- package/src/console/components/Banner.ts +334 -0
- package/src/console/components/Composer.ts +94 -0
- package/src/console/components/StatusBar.ts +49 -0
- package/src/console/components/TerminalConsole.ts +1090 -0
- package/src/console/components/WorkingIndicator.ts +98 -0
- package/src/console/components/banner-sweep.ts +24 -0
- package/src/console/components/welcome.ts +74 -0
- package/src/console/contract.ts +630 -0
- package/src/console/index.ts +34 -0
- package/src/console/input/complete.ts +127 -0
- package/src/console/input/dir-reader.ts +34 -0
- package/src/console/input/index.ts +23 -0
- package/src/console/input/keymap.ts +159 -0
- package/src/console/input/paste.ts +104 -0
- package/src/console/mount.ts +56 -0
- package/src/console/overlays/approval-queue.ts +57 -0
- package/src/console/overlays/approval.ts +130 -0
- package/src/console/overlays/auth.ts +342 -0
- package/src/console/overlays/boards.ts +308 -0
- package/src/console/overlays/host.ts +36 -0
- package/src/console/overlays/index.ts +26 -0
- package/src/console/overlays/pickers.ts +258 -0
- package/src/console/overlays/sessions.ts +190 -0
- package/src/console/reducer.ts +182 -0
- package/src/console/slash/builtins.ts +81 -0
- package/src/console/slash/commands/dynamic.ts +83 -0
- package/src/console/slash/commands/integrations.ts +695 -0
- package/src/console/slash/commands/shared.ts +75 -0
- package/src/console/slash/commands/transcript.ts +263 -0
- package/src/console/slash/commands/workbench.ts +246 -0
- package/src/console/slash/index.ts +15 -0
- package/src/console/slash/registry.ts +70 -0
- package/src/console/slash/resolve.ts +63 -0
- package/src/console/startup.ts +209 -0
- package/src/console/theme/adapter.ts +45 -0
- package/src/console/theme/index.ts +7 -0
- package/src/console/theme/palette.ts +68 -0
- package/src/console/theme/resolve.ts +39 -0
- package/src/console/theme/tokens.ts +71 -0
- package/src/entry.ts +55 -0
- package/src/guardrails.ts +37 -0
- package/src/index.ts +18 -0
- package/src/insight/channel.ts +88 -0
- package/src/insight/contract.ts +185 -0
- package/src/insight/index.ts +110 -0
- package/src/insight/recorder.ts +213 -0
- package/src/insight/redaction.ts +157 -0
- package/src/insight/replay.ts +158 -0
- package/src/insight/sampling.ts +70 -0
- package/src/insight/serialize.ts +50 -0
- package/src/insight/sinks/console.ts +64 -0
- package/src/insight/sinks/file.ts +40 -0
- package/src/insight/sinks/index.ts +24 -0
- package/src/insight/sinks/stream.ts +54 -0
- package/src/integrations/sarvam/attach.ts +239 -0
- package/src/integrations/sarvam/config.ts +156 -0
- package/src/integrations/sarvam/index.ts +25 -0
- package/src/integrations/sarvam/sarvam.test.ts +60 -0
- package/src/integrations/sarvam/types.ts +27 -0
- package/src/integrations/zoho/attach.ts +342 -0
- package/src/integrations/zoho/config.ts +125 -0
- package/src/integrations/zoho/index.ts +27 -0
- package/src/integrations/zoho/types.ts +21 -0
- package/src/integrations/zoho/zoho.test.ts +50 -0
- package/src/kit/clipboard-image.ts +107 -0
- package/src/kit/external-editor.ts +48 -0
- package/src/kit/image.ts +59 -0
- package/src/kit/index.ts +51 -0
- package/src/kit/shell.ts +19 -0
- package/src/kit/tool-fetch.ts +85 -0
- package/src/launch/catalog.ts +148 -0
- package/src/launch/contract.ts +187 -0
- package/src/launch/credentials.ts +625 -0
- package/src/launch/index.ts +98 -0
- package/src/launch/invocation/attachments.ts +179 -0
- package/src/launch/invocation/flags.ts +196 -0
- package/src/launch/invocation/index.ts +25 -0
- package/src/launch/invocation/read.ts +260 -0
- package/src/launch/invocation/usage.ts +67 -0
- package/src/launch/login.ts +324 -0
- package/src/launch/oauth.test.ts +18 -0
- package/src/launch/oauth.ts +203 -0
- package/src/launch/packages.ts +194 -0
- package/src/launch/pickers.ts +189 -0
- package/src/runtime-bridge/bridges/_drive.ts +96 -0
- package/src/runtime-bridge/bridges/builtins.ts +68 -0
- package/src/runtime-bridge/bridges/claude-cli.ts +123 -0
- package/src/runtime-bridge/bridges/codex-cli.ts +142 -0
- package/src/runtime-bridge/bridges/index.ts +33 -0
- package/src/runtime-bridge/bridges/indusagi-cli.ts +155 -0
- package/src/runtime-bridge/broker.ts +227 -0
- package/src/runtime-bridge/contract.ts +122 -0
- package/src/runtime-bridge/index.ts +79 -0
- package/src/runtime-bridge/sink.ts +180 -0
- package/src/sessions/contract.ts +81 -0
- package/src/sessions/index.ts +13 -0
- package/src/sessions/library.ts +229 -0
- package/src/settings/contract.ts +114 -0
- package/src/settings/index.ts +32 -0
- package/src/settings/manager.ts +117 -0
- package/src/transcript-export/index.ts +45 -0
- package/src/transcript-export/publish.ts +260 -0
- package/src/transcript-export/sgr.ts +315 -0
- package/src/transcript-export/template.ts +272 -0
- package/src/transcript-export/theme-bridge.ts +150 -0
- package/src/window-budget/budget/estimate.ts +135 -0
- package/src/window-budget/budget/gate.ts +33 -0
- package/src/window-budget/budget/index.ts +16 -0
- package/src/window-budget/budget/slice.ts +56 -0
- package/src/window-budget/condenser.ts +58 -0
- package/src/window-budget/contract.ts +184 -0
- package/src/window-budget/index.ts +19 -0
- package/src/window-budget/microcompact.ts +95 -0
- package/src/window-budget/rehydrate.ts +136 -0
- package/src/window-budget/summarize/condense.ts +103 -0
- package/src/window-budget/summarize/index.ts +14 -0
- package/src/window-budget/summarize/prompt.ts +149 -0
- package/src/workflow-engine/agent-runner.ts +181 -0
- package/src/workflow-engine/display.ts +224 -0
- package/src/workflow-engine/engine.ts +294 -0
- package/src/workflow-engine/index.ts +23 -0
- package/src/workflow-engine/parse.ts +172 -0
- package/src/workflow-engine/structured-output.ts +35 -0
- package/src/workspace/brand.ts +29 -0
- package/src/workspace/index.ts +18 -0
- package/src/workspace/locator.ts +103 -0
- package/src/workspace/runtime-detect.ts +64 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Window-budget — the condenser factory (the conductor-consumable seam).
|
|
3
|
+
*
|
|
4
|
+
* {@link createCondenser} ties the three pure pieces together into a single
|
|
5
|
+
* function the conductor can drop into its auto-compaction hook.
|
|
6
|
+
*/
|
|
7
|
+
import type {
|
|
8
|
+
AgentMessage,
|
|
9
|
+
BudgetPolicy,
|
|
10
|
+
Condenser,
|
|
11
|
+
CondenserDeps,
|
|
12
|
+
Summary,
|
|
13
|
+
} from "./contract.js";
|
|
14
|
+
import { isOverBudget } from "./budget/gate.js";
|
|
15
|
+
import { planSlice } from "./budget/slice.js";
|
|
16
|
+
import { condenseScope, summarize, type SummarizeDeps } from "./summarize/index.js";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The fallback {@link BudgetPolicy} when the caller supplies none.
|
|
20
|
+
*/
|
|
21
|
+
export const AUTO_CONDENSE_POLICY: BudgetPolicy = {
|
|
22
|
+
triggerRatio: 0.75,
|
|
23
|
+
keepRecent: 6e3,
|
|
24
|
+
reserveTokens: 2048,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Build a {@link Condenser} from a {@link CondenserDeps} bundle. The result plugs
|
|
29
|
+
* straight into the conductor's `CondenseFn` seam.
|
|
30
|
+
*/
|
|
31
|
+
export function createCondenser(deps: CondenserDeps = {}): Condenser {
|
|
32
|
+
const policy = deps.policy ?? AUTO_CONDENSE_POLICY;
|
|
33
|
+
const model = deps.model;
|
|
34
|
+
const complete = deps.complete;
|
|
35
|
+
return async (messages: AgentMessage[]): Promise<AgentMessage[]> => {
|
|
36
|
+
if (!model) return messages;
|
|
37
|
+
if (!isOverBudget(messages, model, policy)) return messages;
|
|
38
|
+
const plan = planSlice(messages, policy);
|
|
39
|
+
if (plan.cut === 0 || plan.dropped.length === 0) {
|
|
40
|
+
return messages;
|
|
41
|
+
}
|
|
42
|
+
const summary = await summarize(plan.dropped, { complete, model });
|
|
43
|
+
return [summary.message, ...plan.kept];
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Session-scope summarization: fold a slice of dropped messages into one digest
|
|
49
|
+
* for the active session.
|
|
50
|
+
*/
|
|
51
|
+
export function condense(
|
|
52
|
+
messages: AgentMessage[],
|
|
53
|
+
deps: Omit<SummarizeDeps, "scope"> = {},
|
|
54
|
+
): Promise<Summary> {
|
|
55
|
+
return summarize(messages, { ...deps, scope: "session" });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export { condenseScope };
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
// Type declarations recovered from dist/types (no runtime body)
|
|
3
|
+
/**
|
|
4
|
+
* Window-budget contract — the FROZEN type surface of the context-window
|
|
5
|
+
* budgeting subsystem (Phase 3, subsystem 05).
|
|
6
|
+
*
|
|
7
|
+
* A long-running coding session accrues messages — user turns, assistant turns,
|
|
8
|
+
* tool calls and their results — until the transcript approaches the model's
|
|
9
|
+
* context window. This subsystem keeps the session usable by *condensing* older
|
|
10
|
+
* history into a single structured summary message while keeping a verbatim
|
|
11
|
+
* tail of the most-recent turns. It answers three questions:
|
|
12
|
+
*
|
|
13
|
+
* 1. **Budget** — *when* are we over budget? A {@link BudgetPolicy} carries
|
|
14
|
+
* config-sourced thresholds (no magic literals); {@link isOverBudget}
|
|
15
|
+
* decides from a real {@link TokenEstimate}.
|
|
16
|
+
* 2. **Slice** — *where* do we cut? {@link planSlice} computes a
|
|
17
|
+
* {@link CondensePlan} via a forward prefix-sum + binary search over a
|
|
18
|
+
* cumulative-token array, never splitting a tool_call from its tool_result.
|
|
19
|
+
* 3. **Condense** — *how* do we compress the dropped portion? A
|
|
20
|
+
* {@link Condenser} flattens the dropped messages, asks an injectable model
|
|
21
|
+
* completer for a structured {@link Summary}, and returns the rebuilt
|
|
22
|
+
* transcript (summary + kept tail).
|
|
23
|
+
*
|
|
24
|
+
* This file declares *only* shapes plus the function-type seams — no behavior,
|
|
25
|
+
* no I/O, no prompt strings. Every later window-budget module (the meter, the
|
|
26
|
+
* slice planner, the condenser, the branch archivist, the prompt templates, and
|
|
27
|
+
* the public barrel) is written against the names declared here.
|
|
28
|
+
*
|
|
29
|
+
* Design stance:
|
|
30
|
+
* - Thresholds are **configuration, not constants**. {@link BudgetPolicy}
|
|
31
|
+
* fields are supplied by the caller; this module bakes in no fixed token
|
|
32
|
+
* fingerprints. Defaults, if any, live in the implementation and are
|
|
33
|
+
* computed relative to the model's own context window.
|
|
34
|
+
* - Branch-summarization is **not a separate engine**. It collapses into the
|
|
35
|
+
* condenser behind a {@link CondenseScope} flag (`"session" | "branch"`),
|
|
36
|
+
* so there is one prompt-assembly path, one token estimator, one slicer.
|
|
37
|
+
* - The model completer is **injectable** ({@link CompleteFn}, default the
|
|
38
|
+
* framework's `completeSimple`) so the condenser runs in tests with no
|
|
39
|
+
* network.
|
|
40
|
+
* - The produced condenser is **conductor-consumable**: a {@link Condenser}
|
|
41
|
+
* is structurally a conductor `CondenseFn`
|
|
42
|
+
* (`(messages: AgentMessage[]) => AgentMessage[] | Promise<AgentMessage[]>`),
|
|
43
|
+
* so a {@link CondenserDeps}-built condenser plugs straight into the
|
|
44
|
+
* conductor's auto-compaction seam.
|
|
45
|
+
*
|
|
46
|
+
* Framework anchors (all from the `indusagi` package — the sibling rebuilt
|
|
47
|
+
* framework this app targets):
|
|
48
|
+
* - `AgentMessage` ← `indusagi/agent`
|
|
49
|
+
* - `Model`, `Usage`, `completeSimple` (and its `Api`/`AssistantMessage`/
|
|
50
|
+
* `Context`/`SimpleStreamOptions`/`StreamLogger` shapes) ← `indusagi/ai`
|
|
51
|
+
*
|
|
52
|
+
* This module never re-declares these; it composes them.
|
|
53
|
+
*/
|
|
54
|
+
import type { AgentMessage } from "indusagi/agent";
|
|
55
|
+
import type { Api, AssistantMessage, Context, Model, SimpleStreamOptions, StreamLogger, Usage } from "indusagi/ai";
|
|
56
|
+
/** Re-exported framework vocabulary window-budget consumers routinely need. */
|
|
57
|
+
export type { AgentMessage, Model, Usage };
|
|
58
|
+
/**
|
|
59
|
+
* The config-sourced thresholds that govern when and how the transcript is
|
|
60
|
+
* condensed. Every field is a *number the caller supplies* — there are no magic
|
|
61
|
+
* token literals baked into this contract. An implementation may
|
|
62
|
+
* provide defaults, but they are configuration values, not protected constants,
|
|
63
|
+
* and deliberately differ from the legacy fingerprints.
|
|
64
|
+
*/
|
|
65
|
+
export interface BudgetPolicy {
|
|
66
|
+
/**
|
|
67
|
+
* Fraction of the model's `contextWindow` at which condensing is triggered,
|
|
68
|
+
* in `(0, 1]`. The meter is "over budget" once the estimated context tokens
|
|
69
|
+
* cross `contextWindow * triggerRatio`. Expressing the trigger as a ratio
|
|
70
|
+
* (rather than an absolute reserve) keeps it window-relative and free of
|
|
71
|
+
* baked-in token counts.
|
|
72
|
+
*/
|
|
73
|
+
readonly triggerRatio: number;
|
|
74
|
+
/**
|
|
75
|
+
* How much of the recent transcript to keep verbatim, measured in estimated
|
|
76
|
+
* tokens. The slice planner preserves a tail of at least this many tokens
|
|
77
|
+
* (snapped to a legal boundary) and condenses everything before it.
|
|
78
|
+
*/
|
|
79
|
+
readonly keepRecent: number;
|
|
80
|
+
/**
|
|
81
|
+
* Optional token headroom to subtract from the window before the trigger is
|
|
82
|
+
* evaluated — a safety margin so a condense fires *before* the very next turn
|
|
83
|
+
* would overflow. When omitted, only {@link triggerRatio} governs the trigger.
|
|
84
|
+
*/
|
|
85
|
+
readonly reserveTokens?: number;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The outcome of measuring a transcript against a model's window. Anchors on the
|
|
89
|
+
* provider's authoritative `usage` count when available (`anchored: true`) and
|
|
90
|
+
* falls back to a rough char/role estimate otherwise; either way `contextTokens`
|
|
91
|
+
* is the figure {@link isOverBudget} compares to `contextWindow`.
|
|
92
|
+
*/
|
|
93
|
+
export interface TokenEstimate {
|
|
94
|
+
/** Best estimate of tokens currently occupying the context window. */
|
|
95
|
+
readonly contextTokens: number;
|
|
96
|
+
/** The model's total context window, in tokens (`Model.contextWindow`). */
|
|
97
|
+
readonly contextWindow: number;
|
|
98
|
+
/**
|
|
99
|
+
* `true` when {@link contextTokens} is anchored on a real provider `usage`
|
|
100
|
+
* figure (only trailing, post-usage messages are estimated); `false` when the
|
|
101
|
+
* whole figure is a heuristic estimate.
|
|
102
|
+
*/
|
|
103
|
+
readonly anchored: boolean;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* The pre-computed result of {@link planSlice}: the chosen cut index and the
|
|
107
|
+
* resulting partition of the transcript.
|
|
108
|
+
*
|
|
109
|
+
* The cut is found by a *forward* prefix-sum + binary search: build a cumulative
|
|
110
|
+
* estimated-token array over the messages, binary-search for the boundary index
|
|
111
|
+
* nearest `total - keepRecent`, then nudge to the closest *legal* boundary —
|
|
112
|
+
* never landing between a `toolCall` and its `toolResult`.
|
|
113
|
+
*
|
|
114
|
+
* Invariants:
|
|
115
|
+
* - `kept.length + dropped.length === messages.length`
|
|
116
|
+
* - `dropped` is the prefix `messages[0 .. cut)` (the older slice to condense)
|
|
117
|
+
* - `kept` is the suffix `messages[cut ..]` (the verbatim recent tail)
|
|
118
|
+
* - `cut` is `0` when nothing is condensable (everything kept).
|
|
119
|
+
*/
|
|
120
|
+
export interface CondensePlan {
|
|
121
|
+
/** Index of the legal cut boundary: `dropped = messages.slice(0, cut)`. */
|
|
122
|
+
readonly cut: number;
|
|
123
|
+
/** The verbatim recent tail preserved as-is (`messages.slice(cut)`). */
|
|
124
|
+
readonly kept: AgentMessage[];
|
|
125
|
+
/** The older slice to be folded into a {@link Summary} (`messages.slice(0, cut)`). */
|
|
126
|
+
readonly dropped: AgentMessage[];
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Which kind of condensing run this is — the flag that collapses
|
|
130
|
+
* branch-summarization into the single condenser path:
|
|
131
|
+
* - `"session"` — condense the *active* transcript in place (the trigger /
|
|
132
|
+
* overflow path); keeps a recent tail, summarizes the head.
|
|
133
|
+
* - `"branch"` — archive an *abandoned* branch into one summary message so its
|
|
134
|
+
* context isn't lost on tree navigation; no verbatim tail is retained.
|
|
135
|
+
*/
|
|
136
|
+
export type CondenseScope = "session" | "branch";
|
|
137
|
+
/**
|
|
138
|
+
* The structured result of summarizing a slice of dropped messages: a single
|
|
139
|
+
* synthetic {@link AgentMessage} that stands in for the messages it covers.
|
|
140
|
+
*/
|
|
141
|
+
export interface Summary {
|
|
142
|
+
/** The synthetic summary message to splice into the rebuilt transcript. */
|
|
143
|
+
readonly message: AgentMessage;
|
|
144
|
+
/** How many source messages this summary replaces. */
|
|
145
|
+
readonly coveredCount: number;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* The injectable model-completion function. Structurally identical to the
|
|
149
|
+
* framework's `completeSimple`, so the real `completeSimple` is the drop-in
|
|
150
|
+
* default and a test can pass a no-network stub of the same shape. The
|
|
151
|
+
* condenser uses this single call to turn flattened transcript text into a
|
|
152
|
+
* {@link Summary}.
|
|
153
|
+
*/
|
|
154
|
+
export type CompleteFn = <TApi extends Api>(model: Model<TApi>, context: Context, options?: SimpleStreamOptions, logger?: StreamLogger) => Promise<AssistantMessage>;
|
|
155
|
+
/**
|
|
156
|
+
* A condenser: takes the active branch's messages and returns the rebuilt
|
|
157
|
+
* transcript (condensed head + verbatim tail, or the input unchanged when there
|
|
158
|
+
* is nothing to do).
|
|
159
|
+
*
|
|
160
|
+
* This type is **structurally compatible with the conductor's `CondenseFn`**
|
|
161
|
+
* (`(messages: AgentMessage[]) => AgentMessage[] | Promise<AgentMessage[]>`), so
|
|
162
|
+
* the result of the condenser factory plugs directly into the conductor's
|
|
163
|
+
* auto-compaction seam with no adapter.
|
|
164
|
+
*/
|
|
165
|
+
export type Condenser = (messages: AgentMessage[]) => AgentMessage[] | Promise<AgentMessage[]>;
|
|
166
|
+
/**
|
|
167
|
+
* Dependencies for building a {@link Condenser}. All fields are optional so a
|
|
168
|
+
* bare `createCondenser()` yields a working, network-free-testable condenser:
|
|
169
|
+
* - `complete` defaults to the framework's `completeSimple`.
|
|
170
|
+
* - `policy` defaults to the implementation's config-sourced thresholds.
|
|
171
|
+
* - `model` is the summarization model; when omitted the condenser may fall
|
|
172
|
+
* back to a no-op (return input unchanged) rather than guess a model.
|
|
173
|
+
*/
|
|
174
|
+
export interface CondenserDeps {
|
|
175
|
+
/**
|
|
176
|
+
* The injectable model completer (default: framework `completeSimple`). Inject
|
|
177
|
+
* a stub of {@link CompleteFn} shape to run the condenser with no network.
|
|
178
|
+
*/
|
|
179
|
+
readonly complete?: CompleteFn;
|
|
180
|
+
/** The model used to write the summary. When omitted, condensing is a no-op. */
|
|
181
|
+
readonly model?: Model<Api>;
|
|
182
|
+
/** The config-sourced budget thresholds (default: implementation defaults). */
|
|
183
|
+
readonly policy?: BudgetPolicy;
|
|
184
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
// Type declarations recovered from dist/types (no runtime body)
|
|
3
|
+
/**
|
|
4
|
+
* Window-budget — public barrel.
|
|
5
|
+
*
|
|
6
|
+
* The context-window budgeting subsystem: token measurement, slice planning,
|
|
7
|
+
* and transcript condensing (with branch-archival collapsed in behind a scope
|
|
8
|
+
* flag). Re-exports the frozen contract types plus the live functions: the
|
|
9
|
+
* budget math (estimateTokens / isOverBudget / planSlice), the summarization core
|
|
10
|
+
* (summarize / condenseScope), and the conductor-consumable condenser factory
|
|
11
|
+
* (createCondenser / condense).
|
|
12
|
+
*/
|
|
13
|
+
export type { AgentMessage, BudgetPolicy, CompleteFn, CondensePlan, Condenser, CondenserDeps, CondenseScope, Model, Summary, TokenEstimate, Usage, } from "./contract.js";
|
|
14
|
+
export { budgetLimit, estimateMessageTokens, estimateTokens, isOverBudget, planSlice, prefixTokens, } from "./budget/index.js";
|
|
15
|
+
export { buildSummaryPrompt, CONDENSER_BRIEF, flattenTranscript, summarize, } from "./summarize/index.js";
|
|
16
|
+
export type { SummarizeDeps } from "./summarize/index.js";
|
|
17
|
+
export { AUTO_CONDENSE_POLICY, condense, condenseScope, createCondenser } from "./condenser.js";
|
|
18
|
+
export { CLEARED_TOOL_RESULT, clearStaleToolResults, COMPACTABLE_TOOL_NAMES, } from "./microcompact.js";
|
|
19
|
+
export { rehydrateRecentReads, RESTORED_FILE_PREFIX } from "./rehydrate.js";
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Window-budget / microcompact — clear stale tool-result bodies in place.
|
|
3
|
+
*/
|
|
4
|
+
import type { AgentMessage } from "./contract.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The placeholder spliced in where a stale tool-result body used to be.
|
|
8
|
+
*/
|
|
9
|
+
export const CLEARED_TOOL_RESULT = "[Old tool result content cleared]";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The wire names of tools whose results are safe to clear once stale.
|
|
13
|
+
*/
|
|
14
|
+
export const COMPACTABLE_TOOL_NAMES: ReadonlySet<string> = new Set([
|
|
15
|
+
"read",
|
|
16
|
+
"grep",
|
|
17
|
+
"find",
|
|
18
|
+
"ls",
|
|
19
|
+
"glob",
|
|
20
|
+
"bash",
|
|
21
|
+
"websearch",
|
|
22
|
+
"webfetch",
|
|
23
|
+
"edit",
|
|
24
|
+
"write",
|
|
25
|
+
]);
|
|
26
|
+
|
|
27
|
+
const DEFAULT_KEEP_RECENT = 6;
|
|
28
|
+
|
|
29
|
+
function isRecord3(value: unknown): value is Record<string, unknown> {
|
|
30
|
+
return typeof value === "object" && value !== null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function collectCompactableToolIds(messages: AgentMessage[]): Set<string> {
|
|
34
|
+
const ids = new Set<string>();
|
|
35
|
+
for (const message of messages) {
|
|
36
|
+
if (!isRecord3(message) || message.role !== "assistant") continue;
|
|
37
|
+
const content = Array.isArray(message.content) ? message.content : [];
|
|
38
|
+
for (const block of content) {
|
|
39
|
+
if (!isRecord3(block) || block.type !== "toolCall") continue;
|
|
40
|
+
const name = typeof block.name === "string" ? block.name : "";
|
|
41
|
+
const id = typeof block.id === "string" ? block.id : "";
|
|
42
|
+
if (id.length > 0 && COMPACTABLE_TOOL_NAMES.has(name)) ids.add(id);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return ids;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function isAlreadyCleared(message: AgentMessage): boolean {
|
|
49
|
+
if (!isRecord3(message)) return false;
|
|
50
|
+
const content = (message as { content?: unknown }).content;
|
|
51
|
+
if (!Array.isArray(content) || content.length !== 1) return false;
|
|
52
|
+
const block = content[0];
|
|
53
|
+
return (
|
|
54
|
+
isRecord3(block) &&
|
|
55
|
+
block.type === "text" &&
|
|
56
|
+
block.text === CLEARED_TOOL_RESULT
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Clear the bodies of stale compactable tool results, keeping the most recent
|
|
62
|
+
* `keepRecent` of them verbatim.
|
|
63
|
+
*/
|
|
64
|
+
export function clearStaleToolResults(
|
|
65
|
+
messages: AgentMessage[],
|
|
66
|
+
opts: { keepRecent?: number } = {},
|
|
67
|
+
): AgentMessage[] {
|
|
68
|
+
const keepRecent = Math.max(1, opts.keepRecent ?? DEFAULT_KEEP_RECENT);
|
|
69
|
+
const compactableIds = collectCompactableToolIds(messages);
|
|
70
|
+
if (compactableIds.size === 0) return messages;
|
|
71
|
+
const clearAt = new Set<number>();
|
|
72
|
+
let kept = 0;
|
|
73
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
74
|
+
const message = messages[i];
|
|
75
|
+
if (!isRecord3(message) || message.role !== "toolResult") continue;
|
|
76
|
+
const id = typeof (message as { toolCallId?: unknown }).toolCallId === "string"
|
|
77
|
+
? (message as { toolCallId: string }).toolCallId
|
|
78
|
+
: "";
|
|
79
|
+
if (!compactableIds.has(id)) continue;
|
|
80
|
+
if (kept < keepRecent) {
|
|
81
|
+
kept++;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (isAlreadyCleared(message as AgentMessage)) continue;
|
|
85
|
+
clearAt.add(i);
|
|
86
|
+
}
|
|
87
|
+
if (clearAt.size === 0) return messages;
|
|
88
|
+
return messages.map((message, i) => {
|
|
89
|
+
if (!clearAt.has(i)) return message;
|
|
90
|
+
return {
|
|
91
|
+
...message,
|
|
92
|
+
content: [{ type: "text", text: CLEARED_TOOL_RESULT }],
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Window-budget / rehydrate — re-attach recently-read files after a condense.
|
|
3
|
+
*/
|
|
4
|
+
import type { AgentMessage } from "./contract.js";
|
|
5
|
+
import { estimateMessageTokens } from "./budget/estimate.js";
|
|
6
|
+
|
|
7
|
+
/** Prefix marking a synthetic message that restores a file body post-compaction. */
|
|
8
|
+
export const RESTORED_FILE_PREFIX = "[Restored file after compaction]";
|
|
9
|
+
|
|
10
|
+
const DEFAULT_MAX_FILES = 5;
|
|
11
|
+
const DEFAULT_TOKEN_BUDGET = 8e3;
|
|
12
|
+
const DEFAULT_READ_TOOL_NAME = "read";
|
|
13
|
+
|
|
14
|
+
function isRecord4(value: unknown): value is Record<string, unknown> {
|
|
15
|
+
return typeof value === "object" && value !== null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function resultBodyText(message: AgentMessage): string {
|
|
19
|
+
if (!isRecord4(message)) return "";
|
|
20
|
+
const content = (message as { content?: unknown }).content;
|
|
21
|
+
if (!Array.isArray(content)) return "";
|
|
22
|
+
const parts: string[] = [];
|
|
23
|
+
for (const block of content) {
|
|
24
|
+
if (
|
|
25
|
+
isRecord4(block) &&
|
|
26
|
+
block.type === "text" &&
|
|
27
|
+
typeof block.text === "string"
|
|
28
|
+
) {
|
|
29
|
+
parts.push(block.text);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return parts.join("\n");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function collectVisibleReadPaths(kept: AgentMessage[], readToolName: string): Set<string> {
|
|
36
|
+
const paths = new Set<string>();
|
|
37
|
+
for (const message of kept) {
|
|
38
|
+
if (!isRecord4(message) || message.role !== "assistant") continue;
|
|
39
|
+
const content = Array.isArray(message.content) ? message.content : [];
|
|
40
|
+
for (const block of content) {
|
|
41
|
+
if (!isRecord4(block) || block.type !== "toolCall") continue;
|
|
42
|
+
if (block.name !== readToolName) continue;
|
|
43
|
+
const args = isRecord4(block.arguments) ? block.arguments : undefined;
|
|
44
|
+
const path = args && typeof args.path === "string" ? args.path : "";
|
|
45
|
+
if (path.length > 0) paths.add(path);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return paths;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface DroppedRead {
|
|
52
|
+
order: number;
|
|
53
|
+
path: string;
|
|
54
|
+
body: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function collectDroppedReads(
|
|
58
|
+
dropped: AgentMessage[],
|
|
59
|
+
readToolName: string,
|
|
60
|
+
): DroppedRead[] {
|
|
61
|
+
const calls = new Map<string, { path: string; order: number }>();
|
|
62
|
+
for (let i = 0; i < dropped.length; i++) {
|
|
63
|
+
const message = dropped[i];
|
|
64
|
+
if (!isRecord4(message) || message.role !== "assistant") continue;
|
|
65
|
+
const content = Array.isArray(message.content) ? message.content : [];
|
|
66
|
+
for (const block of content) {
|
|
67
|
+
if (!isRecord4(block) || block.type !== "toolCall") continue;
|
|
68
|
+
if (block.name !== readToolName) continue;
|
|
69
|
+
const id = typeof block.id === "string" ? block.id : "";
|
|
70
|
+
const args = isRecord4(block.arguments) ? block.arguments : undefined;
|
|
71
|
+
const path = args && typeof args.path === "string" ? args.path : "";
|
|
72
|
+
if (id.length > 0 && path.length > 0) calls.set(id, { path, order: i });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (calls.size === 0) return [];
|
|
76
|
+
const byPath = new Map<string, DroppedRead>();
|
|
77
|
+
for (let i = 0; i < dropped.length; i++) {
|
|
78
|
+
const message = dropped[i];
|
|
79
|
+
if (!isRecord4(message) || message.role !== "toolResult") continue;
|
|
80
|
+
if ((message as { isError?: unknown }).isError === true) continue;
|
|
81
|
+
const id = typeof (message as { toolCallId?: unknown }).toolCallId === "string"
|
|
82
|
+
? (message as { toolCallId: string }).toolCallId
|
|
83
|
+
: "";
|
|
84
|
+
const call = calls.get(id);
|
|
85
|
+
if (call === undefined) continue;
|
|
86
|
+
const body = resultBodyText(message as AgentMessage);
|
|
87
|
+
if (body.length === 0) continue;
|
|
88
|
+
byPath.set(call.path, { order: i, path: call.path, body });
|
|
89
|
+
}
|
|
90
|
+
return [...byPath.values()];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Build the synthetic user messages that re-attach the most-recently-read files
|
|
95
|
+
* dropped by a condense.
|
|
96
|
+
*/
|
|
97
|
+
export function rehydrateRecentReads(
|
|
98
|
+
dropped: AgentMessage[],
|
|
99
|
+
kept: AgentMessage[],
|
|
100
|
+
opts: {
|
|
101
|
+
maxFiles?: number;
|
|
102
|
+
tokenBudget?: number;
|
|
103
|
+
readToolName?: string;
|
|
104
|
+
} = {},
|
|
105
|
+
): AgentMessage[] {
|
|
106
|
+
const maxFiles = Math.max(0, opts.maxFiles ?? DEFAULT_MAX_FILES);
|
|
107
|
+
const tokenBudget = Math.max(0, opts.tokenBudget ?? DEFAULT_TOKEN_BUDGET);
|
|
108
|
+
const readToolName = opts.readToolName ?? DEFAULT_READ_TOOL_NAME;
|
|
109
|
+
if (maxFiles === 0 || tokenBudget === 0) return [];
|
|
110
|
+
const reads = collectDroppedReads(dropped, readToolName);
|
|
111
|
+
if (reads.length === 0) return [];
|
|
112
|
+
const visible = collectVisibleReadPaths(kept, readToolName);
|
|
113
|
+
const candidates = reads
|
|
114
|
+
.filter((r) => !visible.has(r.path))
|
|
115
|
+
.sort((a, b) => b.order - a.order)
|
|
116
|
+
.slice(0, maxFiles);
|
|
117
|
+
if (candidates.length === 0) return [];
|
|
118
|
+
const restored: AgentMessage[] = [];
|
|
119
|
+
let spent = 0;
|
|
120
|
+
for (const read of candidates) {
|
|
121
|
+
const message: AgentMessage = {
|
|
122
|
+
role: "user",
|
|
123
|
+
content: `${RESTORED_FILE_PREFIX} ${read.path}\n${read.body}`,
|
|
124
|
+
timestamp: Date.now(),
|
|
125
|
+
};
|
|
126
|
+
const cost = estimateMessageTokens(message);
|
|
127
|
+
if (spent + cost > tokenBudget && restored.length > 0) break;
|
|
128
|
+
if (spent + cost > tokenBudget && restored.length === 0) {
|
|
129
|
+
restored.push(message);
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
restored.push(message);
|
|
133
|
+
spent += cost;
|
|
134
|
+
}
|
|
135
|
+
return restored.reverse();
|
|
136
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Window-budget — model-driven summarization.
|
|
3
|
+
*
|
|
4
|
+
* {@link summarize} is the single condensing primitive: given the dropped prefix
|
|
5
|
+
* of a transcript and a {@link SummarizeDeps} bundle, it flattens those messages,
|
|
6
|
+
* asks the injectable model completer to write a structured digest, and returns a
|
|
7
|
+
* synthetic {@link Summary} message.
|
|
8
|
+
*/
|
|
9
|
+
import type { AgentMessage, CompleteFn, CondenseScope, Model, Summary } from "../contract.js";
|
|
10
|
+
import { completeSimple } from "indusagi/ai";
|
|
11
|
+
import { CONDENSER_BRIEF, buildSummaryPrompt, flattenTranscript } from "./prompt.js";
|
|
12
|
+
|
|
13
|
+
export interface SummarizeDeps {
|
|
14
|
+
/** Injectable completer (default: framework `completeSimple`). */
|
|
15
|
+
readonly complete?: CompleteFn;
|
|
16
|
+
/** The summarization model. When omitted, a deterministic local digest is used. */
|
|
17
|
+
readonly model?: Model<Model<string>["api"]>;
|
|
18
|
+
/** Which kind of condense this is; defaults to `"session"`. */
|
|
19
|
+
readonly scope?: CondenseScope;
|
|
20
|
+
/** An earlier digest to refresh/extend (iterative-refresh / branch carry-in). */
|
|
21
|
+
readonly priorDigest?: string;
|
|
22
|
+
/** Cancellation signal forwarded to the completer. */
|
|
23
|
+
readonly signal?: AbortSignal;
|
|
24
|
+
/** Credential for the summarization model's provider, forwarded to the completer. */
|
|
25
|
+
readonly apiKey?: string;
|
|
26
|
+
/** Optional cap on the digest size, in tokens. */
|
|
27
|
+
readonly maxTokens?: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const DIGEST_HEADER = "[session digest \u2014 older turns condensed]";
|
|
31
|
+
const BRANCH_HEADER = "[branch digest \u2014 archived from a path not taken]";
|
|
32
|
+
|
|
33
|
+
function toSummaryMessage(digest: string, scope: CondenseScope): AgentMessage {
|
|
34
|
+
const header = scope === "branch" ? BRANCH_HEADER : DIGEST_HEADER;
|
|
35
|
+
return {
|
|
36
|
+
role: "user",
|
|
37
|
+
content: `${header}\n\n${digest}`,
|
|
38
|
+
timestamp: Date.now(),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function textOf(message: { content: Array<{ type: string; text?: string }> }): string {
|
|
43
|
+
const parts: string[] = [];
|
|
44
|
+
for (const block of message.content) {
|
|
45
|
+
if (block.type === "text" && block.text && block.text.trim()) parts.push(block.text);
|
|
46
|
+
}
|
|
47
|
+
return parts.join("\n").trim();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function localFallbackDigest(messages: AgentMessage[], priorDigest?: string): string {
|
|
51
|
+
const lines: string[] = [
|
|
52
|
+
`# Carryover`,
|
|
53
|
+
`${messages.length} earlier message(s) were elided without a summarization model bound.`,
|
|
54
|
+
];
|
|
55
|
+
if (priorDigest && priorDigest.trim()) {
|
|
56
|
+
lines.push("", priorDigest.trim());
|
|
57
|
+
}
|
|
58
|
+
return lines.join("\n");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Summarize a slice of dropped messages into a single synthetic {@link Summary}.
|
|
63
|
+
*/
|
|
64
|
+
export async function summarize(
|
|
65
|
+
messages: AgentMessage[],
|
|
66
|
+
deps: SummarizeDeps = {},
|
|
67
|
+
): Promise<Summary> {
|
|
68
|
+
const scope = deps.scope ?? "session";
|
|
69
|
+
const coveredCount = messages.length;
|
|
70
|
+
if (!deps.model) {
|
|
71
|
+
const digest = localFallbackDigest(messages, deps.priorDigest);
|
|
72
|
+
return { message: toSummaryMessage(digest, scope), coveredCount };
|
|
73
|
+
}
|
|
74
|
+
const prompt = buildSummaryPrompt(messages, scope, deps.priorDigest);
|
|
75
|
+
const context = {
|
|
76
|
+
systemPrompt: CONDENSER_BRIEF,
|
|
77
|
+
messages: [{ role: "user", content: prompt, timestamp: Date.now() }],
|
|
78
|
+
};
|
|
79
|
+
const options = {
|
|
80
|
+
reasoning: "high",
|
|
81
|
+
...(deps.maxTokens !== undefined ? { maxTokens: deps.maxTokens } : {}),
|
|
82
|
+
...(deps.signal ? { signal: deps.signal } : {}),
|
|
83
|
+
...(deps.apiKey !== undefined ? { apiKey: deps.apiKey } : {}),
|
|
84
|
+
};
|
|
85
|
+
const complete = deps.complete ?? completeSimple;
|
|
86
|
+
const reply = await complete(deps.model, context, options);
|
|
87
|
+
const digest = textOf(reply as { content: Array<{ type: string; text?: string }> });
|
|
88
|
+
const finalDigest = digest || localFallbackDigest(messages, deps.priorDigest);
|
|
89
|
+
return { message: toSummaryMessage(finalDigest, scope), coveredCount };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Branch-archival entrypoint: condense an abandoned branch into one summary
|
|
94
|
+
* message.
|
|
95
|
+
*/
|
|
96
|
+
export function condenseScope(
|
|
97
|
+
messages: AgentMessage[],
|
|
98
|
+
deps: Omit<SummarizeDeps, "scope"> = {},
|
|
99
|
+
): Promise<Summary> {
|
|
100
|
+
return summarize(messages, { ...deps, scope: "branch" });
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export { flattenTranscript };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
// Type declarations recovered from dist/types (no runtime body)
|
|
3
|
+
/**
|
|
4
|
+
* Window-budget — summarization subsystem barrel.
|
|
5
|
+
*
|
|
6
|
+
* Model-driven condensing of the dropped transcript prefix into one synthetic
|
|
7
|
+
* summary message, with re-authored prompts (new section names + a new tag
|
|
8
|
+
* vocabulary). Branch-archival folds in behind the scope flag — `condenseScope`
|
|
9
|
+
* is the branch entrypoint over the same `summarize` core.
|
|
10
|
+
*/
|
|
11
|
+
export { buildSummaryPrompt, CONDENSER_BRIEF, flattenTranscript, } from "./prompt.js";
|
|
12
|
+
export { condenseScope, summarize } from "./condense.js";
|
|
13
|
+
export type { SummarizeDeps } from "./condense.js";
|
|
14
|
+
export type { AgentMessage, CompleteFn, CondenseScope, Model, Summary, } from "../contract.js";
|